Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(245)

Side by Side Diff: test/cctest/wasm/test-run-wasm.cc

Issue 1504713014: Initial import of v8-native WASM. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/cctest.gyp ('k') | test/cctest/wasm/test-run-wasm-module.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 <stdlib.h>
6 #include <string.h>
7
8 #include "src/compiler/graph-visualizer.h"
9 #include "src/compiler/js-graph.h"
10 #include "src/compiler/wasm-compiler.h"
11
12 #include "src/wasm/ast-decoder.h"
13 #include "src/wasm/wasm-macro-gen.h"
14 #include "src/wasm/wasm-module.h"
15 #include "src/wasm/wasm-opcodes.h"
16
17 #include "test/cctest/cctest.h"
18 #include "test/cctest/compiler/codegen-tester.h"
19 #include "test/cctest/compiler/graph-builder-tester.h"
20 #include "test/cctest/compiler/value-helper.h"
21
22 #include "test/cctest/wasm/test-signatures.h"
23
24 // TODO(titzer): pull WASM_64 up to a common header.
25 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
26 #define WASM_64 1
27 #else
28 #define WASM_64 0
29 #endif
30
31 // TODO(titzer): check traps more robustly in tests.
32 // Currently, in tests, we just return 0xdeadbeef from the function in which
33 // the trap occurs if the runtime context is not available to throw a JavaScript
34 // exception.
35 #define CHECK_TRAP(x) CHECK_EQ(0xdeadbeef, (x)&0xFFFFFFFF)
36
37 using namespace v8::base;
38 using namespace v8::internal;
39 using namespace v8::internal::compiler;
40 using namespace v8::internal::wasm;
41
42 static void init_env(FunctionEnv* env, FunctionSig* sig) {
43 env->module = nullptr;
44 env->sig = sig;
45 env->local_int32_count = 0;
46 env->local_int64_count = 0;
47 env->local_float32_count = 0;
48 env->local_float64_count = 0;
49 env->SumLocals();
50 }
51
52 const int kMaxGlobalsSize = 128;
53
54 // A helper for module environments that adds the ability to allocate memory
55 // and global variables.
56 class TestingModule : public ModuleEnv {
57 public:
58 TestingModule() : mem_size(0), global_offset(0) {
59 globals_area = 0;
60 mem_start = 0;
61 mem_end = 0;
62 module = nullptr;
63 linker = nullptr;
64 function_code = nullptr;
65 asm_js = false;
66 }
67
68 ~TestingModule() {
69 if (mem_start) {
70 free(raw_mem_start<byte>());
71 }
72 if (module) {
73 if (module->globals) delete module->globals;
74 if (module->signatures) delete module->signatures;
75 if (module->functions) delete module->functions;
76 if (globals_area) free(reinterpret_cast<byte*>(globals_area));
77 delete module;
78 }
79 }
80
81 byte* AddMemory(size_t size) {
82 CHECK_EQ(0, mem_start);
83 CHECK_EQ(0, mem_size);
84 mem_start = reinterpret_cast<uintptr_t>(malloc(size));
85 CHECK(mem_start);
86 memset(raw_mem_start<byte>(), 0, size);
87 mem_end = mem_start + size;
88 mem_size = size;
89 return raw_mem_start<byte>();
90 }
91
92 template <typename T>
93 T* AddMemoryElems(size_t count) {
94 AddMemory(count * sizeof(T));
95 return raw_mem_start<T>();
96 }
97
98 template <typename T>
99 T* AddGlobal(MachineType mem_type) {
100 WasmGlobal* global = AddGlobal(mem_type);
101 return reinterpret_cast<T*>(globals_area + global->offset);
102 }
103
104 byte AddSignature(FunctionSig* sig) {
105 AllocModule();
106 if (!module->signatures) {
107 module->signatures = new std::vector<FunctionSig*>();
108 }
109 module->signatures->push_back(sig);
110 size_t size = module->signatures->size();
111 CHECK(size < 127);
112 return static_cast<byte>(size - 1);
113 }
114
115 template <typename T>
116 T* raw_mem_start() {
117 DCHECK(mem_start);
118 return reinterpret_cast<T*>(mem_start);
119 }
120
121 template <typename T>
122 T* raw_mem_end() {
123 DCHECK(mem_start);
124 return reinterpret_cast<T*>(mem_end);
125 }
126
127 template <typename T>
128 T raw_mem_at(int i) {
129 DCHECK(mem_start);
130 return reinterpret_cast<T*>(mem_start)[i];
131 }
132
133 template <typename T>
134 T raw_val_at(int i) {
135 T val;
136 memcpy(&val, reinterpret_cast<void*>(mem_start + i), sizeof(T));
137 return val;
138 }
139
140 // Zero-initialize the memory.
141 void ZeroMemory() { memset(raw_mem_start<byte>(), 0, mem_size); }
142
143 // Pseudo-randomly intialize the memory.
144 void RandomizeMemory(unsigned seed = 88) {
145 byte* raw = raw_mem_start<byte>();
146 byte* end = raw_mem_end<byte>();
147 while (raw < end) {
148 *raw = static_cast<byte>(rand_r(&seed));
149 raw++;
150 }
151 }
152
153 WasmFunction* AddFunction(FunctionSig* sig, Handle<Code> code) {
154 AllocModule();
155 if (module->functions == nullptr) {
156 module->functions = new std::vector<WasmFunction>();
157 function_code = new std::vector<Handle<Code>>();
158 }
159 module->functions->push_back({sig, 0, 0, 0, 0, 0, 0, 0, false, false});
160 function_code->push_back(code);
161 return &module->functions->back();
162 }
163
164 private:
165 size_t mem_size;
166 unsigned global_offset;
167
168 WasmGlobal* AddGlobal(MachineType mem_type) {
169 AllocModule();
170 if (globals_area == 0) {
171 globals_area = reinterpret_cast<uintptr_t>(malloc(kMaxGlobalsSize));
172 module->globals = new std::vector<WasmGlobal>();
173 }
174 byte size = WasmOpcodes::MemSize(mem_type);
175 global_offset = (global_offset + size - 1) & ~(size - 1); // align
176 module->globals->push_back({0, mem_type, global_offset, false});
177 global_offset += size;
178 CHECK_LT(global_offset, kMaxGlobalsSize); // limit number of globals.
179 return &module->globals->back();
180 }
181 void AllocModule() {
182 if (module == nullptr) {
183 module = new WasmModule();
184 module->globals = nullptr;
185 module->functions = nullptr;
186 module->data_segments = nullptr;
187 }
188 }
189 };
190
191
192 // A helper for compiling functions that are only internally callable WASM code.
193 class WasmFunctionCompiler : public HandleAndZoneScope,
194 private GraphAndBuilders {
195 public:
196 explicit WasmFunctionCompiler(FunctionSig* sig)
197 : GraphAndBuilders(main_zone()),
198 jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
199 nullptr, this->machine()),
200 descriptor_(nullptr) {
201 init_env(&env, sig);
202 }
203
204 JSGraph jsgraph;
205 FunctionEnv env;
206 // The call descriptor is initialized when the function is compiled.
207 CallDescriptor* descriptor_;
208
209 Isolate* isolate() { return main_isolate(); }
210 Graph* graph() const { return main_graph_; }
211 Zone* zone() const { return graph()->zone(); }
212 CommonOperatorBuilder* common() { return &main_common_; }
213 MachineOperatorBuilder* machine() { return &main_machine_; }
214 CallDescriptor* descriptor() { return descriptor_; }
215
216 void Build(const byte* start, const byte* end) {
217 compiler::WasmGraphBuilder builder(main_zone(), &jsgraph);
218 TreeResult result = BuildTFGraph(&builder, &env, start, end);
219 if (result.failed()) {
220 ptrdiff_t pc = result.error_pc - result.start;
221 ptrdiff_t pt = result.error_pt - result.start;
222 std::ostringstream str;
223 str << "Verification failed: " << result.error_code << " pc = +" << pc;
224 if (result.error_pt) str << ", pt = +" << pt;
225 str << ", msg = " << result.error_msg.get();
226 FATAL(str.str().c_str());
227 }
228 if (FLAG_trace_turbo_graph) {
229 OFStream os(stdout);
230 os << AsRPO(*jsgraph.graph());
231 }
232 }
233
234 byte AllocateLocal(LocalType type) {
235 int result = static_cast<int>(env.total_locals);
236 env.AddLocals(type, 1);
237 byte b = static_cast<byte>(result);
238 CHECK_EQ(result, b);
239 return b;
240 }
241
242 Handle<Code> Compile(ModuleEnv* module) {
243 descriptor_ = module->GetWasmCallDescriptor(this->zone(), env.sig);
244 CompilationInfo info("wasm compile", this->isolate(), this->zone());
245 Handle<Code> result =
246 Pipeline::GenerateCodeForTesting(&info, descriptor_, this->graph());
247 #if DEBUG
248 if (!result.is_null() && FLAG_print_opt_code) {
249 OFStream os(stdout);
250 result->Disassemble("wasm code", os);
251 }
252 #endif
253
254 return result;
255 }
256
257 unsigned CompileAndAdd(TestingModule* module) {
258 unsigned index = 0;
259 if (module->module && module->module->functions) {
260 index = static_cast<unsigned>(module->module->functions->size());
261 }
262 module->AddFunction(env.sig, Compile(module));
263 return index;
264 }
265 };
266
267
268 // A helper class to build graphs from Wasm bytecode, generate machine
269 // code, and run that code.
270 template <typename ReturnType>
271 class WasmRunner {
272 public:
273 WasmRunner(MachineType p0 = MachineType::None(),
274 MachineType p1 = MachineType::None(),
275 MachineType p2 = MachineType::None(),
276 MachineType p3 = MachineType::None())
277 : signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
278 GetParameterCount(p0, p1, p2, p3), storage_),
279 compiler_(&signature_),
280 call_wrapper_(p0, p1, p2, p3),
281 compilation_done_(false) {
282 int index = 0;
283 MachineType ret = MachineTypeForC<ReturnType>();
284 if (ret != MachineType::None()) {
285 storage_[index++] = WasmOpcodes::LocalTypeFor(ret);
286 }
287 if (p0 != MachineType::None())
288 storage_[index++] = WasmOpcodes::LocalTypeFor(p0);
289 if (p1 != MachineType::None())
290 storage_[index++] = WasmOpcodes::LocalTypeFor(p1);
291 if (p2 != MachineType::None())
292 storage_[index++] = WasmOpcodes::LocalTypeFor(p2);
293 if (p3 != MachineType::None())
294 storage_[index++] = WasmOpcodes::LocalTypeFor(p3);
295 }
296
297
298 FunctionEnv* env() { return &compiler_.env; }
299
300
301 // Builds a graph from the given Wasm code, and generates the machine
302 // code and call wrapper for that graph. This method must not be called
303 // more than once.
304 void Build(const byte* start, const byte* end) {
305 DCHECK(!compilation_done_);
306 compilation_done_ = true;
307 // Build the TF graph.
308 compiler_.Build(start, end);
309 // Generate code.
310 Handle<Code> code = compiler_.Compile(env()->module);
311
312 // Construct the call wrapper.
313 Node* inputs[5];
314 int input_count = 0;
315 inputs[input_count++] = call_wrapper_.HeapConstant(code);
316 for (int i = 0; i < signature_.parameter_count(); i++) {
317 inputs[input_count++] = call_wrapper_.Parameter(i);
318 }
319
320 call_wrapper_.Return(call_wrapper_.AddNode(
321 call_wrapper_.common()->Call(compiler_.descriptor()), input_count,
322 inputs));
323 }
324
325
326 ReturnType Call() { return call_wrapper_.Call(); }
327
328
329 template <typename P0>
330 ReturnType Call(P0 p0) {
331 return call_wrapper_.Call(p0);
332 }
333
334
335 template <typename P0, typename P1>
336 ReturnType Call(P0 p0, P1 p1) {
337 return call_wrapper_.Call(p0, p1);
338 }
339
340
341 template <typename P0, typename P1, typename P2>
342 ReturnType Call(P0 p0, P1 p1, P2 p2) {
343 return call_wrapper_.Call(p0, p1, p2);
344 }
345
346
347 template <typename P0, typename P1, typename P2, typename P3>
348 ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
349 return call_wrapper_.Call(p0, p1, p2, p3);
350 }
351
352
353 byte AllocateLocal(LocalType type) {
354 int result = static_cast<int>(env()->total_locals);
355 env()->AddLocals(type, 1);
356 byte b = static_cast<byte>(result);
357 CHECK_EQ(result, b);
358 return b;
359 }
360
361
362 private:
363 LocalType storage_[5];
364 FunctionSig signature_;
365 WasmFunctionCompiler compiler_;
366 BufferedRawMachineAssemblerTester<ReturnType> call_wrapper_;
367 bool compilation_done_;
368
369 static size_t GetParameterCount(MachineType p0, MachineType p1,
370 MachineType p2, MachineType p3) {
371 if (p0 == MachineType::None()) return 0;
372 if (p1 == MachineType::None()) return 1;
373 if (p2 == MachineType::None()) return 2;
374 if (p3 == MachineType::None()) return 3;
375 return 4;
376 }
377 };
378
379 #define BUILD(r, ...) \
380 do { \
381 byte code[] = {__VA_ARGS__}; \
382 r.Build(code, code + arraysize(code)); \
383 } while (false)
384
385
386 TEST(Run_WasmInt8Const) {
387 WasmRunner<int8_t> r;
388 const byte kExpectedValue = 121;
389 // return(kExpectedValue)
390 BUILD(r, WASM_I8(kExpectedValue));
391 CHECK_EQ(kExpectedValue, r.Call());
392 }
393
394
395 TEST(Run_WasmInt8Const_fallthru1) {
396 WasmRunner<int8_t> r;
397 const byte kExpectedValue = 122;
398 // kExpectedValue
399 BUILD(r, WASM_I8(kExpectedValue));
400 CHECK_EQ(kExpectedValue, r.Call());
401 }
402
403
404 TEST(Run_WasmInt8Const_fallthru2) {
405 WasmRunner<int8_t> r;
406 const byte kExpectedValue = 123;
407 // -99 kExpectedValue
408 BUILD(r, WASM_I8(-99), WASM_I8(kExpectedValue));
409 CHECK_EQ(kExpectedValue, r.Call());
410 }
411
412
413 TEST(Run_WasmInt8Const_all) {
414 for (int value = -128; value <= 127; value++) {
415 WasmRunner<int8_t> r;
416 // return(value)
417 BUILD(r, WASM_I8(value));
418 int8_t result = r.Call();
419 CHECK_EQ(value, result);
420 }
421 }
422
423
424 TEST(Run_WasmInt32Const) {
425 WasmRunner<int32_t> r;
426 const int32_t kExpectedValue = 0x11223344;
427 // return(kExpectedValue)
428 BUILD(r, WASM_I32(kExpectedValue));
429 CHECK_EQ(kExpectedValue, r.Call());
430 }
431
432
433 TEST(Run_WasmInt32Const_many) {
434 FOR_INT32_INPUTS(i) {
435 WasmRunner<int32_t> r;
436 const int32_t kExpectedValue = *i;
437 // return(kExpectedValue)
438 BUILD(r, WASM_I32(kExpectedValue));
439 CHECK_EQ(kExpectedValue, r.Call());
440 }
441 }
442
443
444 TEST(Run_WasmMemorySize) {
445 WasmRunner<int32_t> r;
446 TestingModule module;
447 module.AddMemory(1024);
448 r.env()->module = &module;
449 BUILD(r, kExprMemorySize);
450 CHECK_EQ(1024, r.Call());
451 }
452
453
454 #if WASM_64
455 TEST(Run_WasmInt64Const) {
456 WasmRunner<int64_t> r;
457 const int64_t kExpectedValue = 0x1122334455667788LL;
458 // return(kExpectedValue)
459 BUILD(r, WASM_I64(kExpectedValue));
460 CHECK_EQ(kExpectedValue, r.Call());
461 }
462
463
464 TEST(Run_WasmInt64Const_many) {
465 int cntr = 0;
466 FOR_INT32_INPUTS(i) {
467 WasmRunner<int64_t> r;
468 const int64_t kExpectedValue = (static_cast<int64_t>(*i) << 32) | cntr;
469 // return(kExpectedValue)
470 BUILD(r, WASM_I64(kExpectedValue));
471 CHECK_EQ(kExpectedValue, r.Call());
472 cntr++;
473 }
474 }
475 #endif
476
477
478 TEST(Run_WasmInt32Param0) {
479 WasmRunner<int32_t> r(MachineType::Int32());
480 // return(local[0])
481 BUILD(r, WASM_GET_LOCAL(0));
482 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
483 }
484
485
486 TEST(Run_WasmInt32Param0_fallthru) {
487 WasmRunner<int32_t> r(MachineType::Int32());
488 // local[0]
489 BUILD(r, WASM_GET_LOCAL(0));
490 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
491 }
492
493
494 TEST(Run_WasmInt32Param1) {
495 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
496 // local[1]
497 BUILD(r, WASM_GET_LOCAL(1));
498 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(-111, *i)); }
499 }
500
501
502 TEST(Run_WasmInt32Add) {
503 WasmRunner<int32_t> r;
504 // 11 + 44
505 BUILD(r, WASM_I32_ADD(WASM_I8(11), WASM_I8(44)));
506 CHECK_EQ(55, r.Call());
507 }
508
509
510 TEST(Run_WasmInt32Add_P) {
511 WasmRunner<int32_t> r(MachineType::Int32());
512 // p0 + 13
513 BUILD(r, WASM_I32_ADD(WASM_I8(13), WASM_GET_LOCAL(0)));
514 FOR_INT32_INPUTS(i) { CHECK_EQ(*i + 13, r.Call(*i)); }
515 }
516
517
518 TEST(Run_WasmInt32Add_P_fallthru) {
519 WasmRunner<int32_t> r(MachineType::Int32());
520 // p0 + 13
521 BUILD(r, WASM_I32_ADD(WASM_I8(13), WASM_GET_LOCAL(0)));
522 FOR_INT32_INPUTS(i) { CHECK_EQ(*i + 13, r.Call(*i)); }
523 }
524
525
526 TEST(Run_WasmInt32Add_P2) {
527 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
528 // p0 + p1
529 BUILD(r, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
530 FOR_INT32_INPUTS(i) {
531 FOR_INT32_INPUTS(j) {
532 int32_t expected = static_cast<int32_t>(static_cast<uint32_t>(*i) +
533 static_cast<uint32_t>(*j));
534 CHECK_EQ(expected, r.Call(*i, *j));
535 }
536 }
537 }
538
539
540 TEST(Run_WasmFloat32Add) {
541 WasmRunner<int32_t> r;
542 // int(11.5f + 44.5f)
543 BUILD(r,
544 WASM_I32_SCONVERT_F32(WASM_F32_ADD(WASM_F32(11.5f), WASM_F32(44.5f))));
545 CHECK_EQ(56, r.Call());
546 }
547
548
549 TEST(Run_WasmFloat64Add) {
550 WasmRunner<int32_t> r;
551 // return int(13.5d + 43.5d)
552 BUILD(r, WASM_I32_SCONVERT_F64(WASM_F64_ADD(WASM_F64(13.5), WASM_F64(43.5))));
553 CHECK_EQ(57, r.Call());
554 }
555
556
557 void TestInt32Binop(WasmOpcode opcode, int32_t expected, int32_t a, int32_t b) {
558 {
559 WasmRunner<int32_t> r;
560 // K op K
561 BUILD(r, WASM_BINOP(opcode, WASM_I32(a), WASM_I32(b)));
562 CHECK_EQ(expected, r.Call());
563 }
564 {
565 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
566 // a op b
567 BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
568 CHECK_EQ(expected, r.Call(a, b));
569 }
570 }
571
572
573 TEST(Run_WasmInt32Binops) {
574 TestInt32Binop(kExprI32Add, 88888888, 33333333, 55555555);
575 TestInt32Binop(kExprI32Sub, -1111111, 7777777, 8888888);
576 TestInt32Binop(kExprI32Mul, 65130756, 88734, 734);
577 TestInt32Binop(kExprI32DivS, -66, -4777344, 72384);
578 TestInt32Binop(kExprI32DivU, 805306368, 0xF0000000, 5);
579 TestInt32Binop(kExprI32RemS, -3, -3003, 1000);
580 TestInt32Binop(kExprI32RemU, 4, 4004, 1000);
581 TestInt32Binop(kExprI32And, 0xEE, 0xFFEE, 0xFF0000FF);
582 TestInt32Binop(kExprI32Ior, 0xF0FF00FF, 0xF0F000EE, 0x000F0011);
583 TestInt32Binop(kExprI32Xor, 0xABCDEF01, 0xABCDEFFF, 0xFE);
584 TestInt32Binop(kExprI32Shl, 0xA0000000, 0xA, 28);
585 TestInt32Binop(kExprI32ShrU, 0x07000010, 0x70000100, 4);
586 TestInt32Binop(kExprI32ShrS, 0xFF000000, 0x80000000, 7);
587 TestInt32Binop(kExprI32Eq, 1, -99, -99);
588 TestInt32Binop(kExprI32Ne, 0, -97, -97);
589
590 TestInt32Binop(kExprI32LtS, 1, -4, 4);
591 TestInt32Binop(kExprI32LeS, 0, -2, -3);
592 TestInt32Binop(kExprI32LtU, 1, 0, -6);
593 TestInt32Binop(kExprI32LeU, 1, 98978, 0xF0000000);
594
595 TestInt32Binop(kExprI32GtS, 1, 4, -4);
596 TestInt32Binop(kExprI32GeS, 0, -3, -2);
597 TestInt32Binop(kExprI32GtU, 1, -6, 0);
598 TestInt32Binop(kExprI32GeU, 1, 0xF0000000, 98978);
599 }
600
601
602 void TestInt32Unop(WasmOpcode opcode, int32_t expected, int32_t a) {
603 {
604 WasmRunner<int32_t> r;
605 // return op K
606 BUILD(r, WASM_UNOP(opcode, WASM_I32(a)));
607 CHECK_EQ(expected, r.Call());
608 }
609 {
610 WasmRunner<int32_t> r(MachineType::Int32());
611 // return op a
612 BUILD(r, WASM_UNOP(opcode, WASM_GET_LOCAL(0)));
613 CHECK_EQ(expected, r.Call(a));
614 }
615 }
616
617
618 TEST(Run_WasmInt32Clz) {
619 TestInt32Unop(kExprI32Clz, 0, 0x80001000);
620 TestInt32Unop(kExprI32Clz, 1, 0x40000500);
621 TestInt32Unop(kExprI32Clz, 2, 0x20000300);
622 TestInt32Unop(kExprI32Clz, 3, 0x10000003);
623 TestInt32Unop(kExprI32Clz, 4, 0x08050000);
624 TestInt32Unop(kExprI32Clz, 5, 0x04006000);
625 TestInt32Unop(kExprI32Clz, 6, 0x02000000);
626 TestInt32Unop(kExprI32Clz, 7, 0x010000a0);
627 TestInt32Unop(kExprI32Clz, 8, 0x00800c00);
628 TestInt32Unop(kExprI32Clz, 9, 0x00400000);
629 TestInt32Unop(kExprI32Clz, 10, 0x0020000d);
630 TestInt32Unop(kExprI32Clz, 11, 0x00100f00);
631 TestInt32Unop(kExprI32Clz, 12, 0x00080000);
632 TestInt32Unop(kExprI32Clz, 13, 0x00041000);
633 TestInt32Unop(kExprI32Clz, 14, 0x00020020);
634 TestInt32Unop(kExprI32Clz, 15, 0x00010300);
635 TestInt32Unop(kExprI32Clz, 16, 0x00008040);
636 TestInt32Unop(kExprI32Clz, 17, 0x00004005);
637 TestInt32Unop(kExprI32Clz, 18, 0x00002050);
638 TestInt32Unop(kExprI32Clz, 19, 0x00001700);
639 TestInt32Unop(kExprI32Clz, 20, 0x00000870);
640 TestInt32Unop(kExprI32Clz, 21, 0x00000405);
641 TestInt32Unop(kExprI32Clz, 22, 0x00000203);
642 TestInt32Unop(kExprI32Clz, 23, 0x00000101);
643 TestInt32Unop(kExprI32Clz, 24, 0x00000089);
644 TestInt32Unop(kExprI32Clz, 25, 0x00000041);
645 TestInt32Unop(kExprI32Clz, 26, 0x00000022);
646 TestInt32Unop(kExprI32Clz, 27, 0x00000013);
647 TestInt32Unop(kExprI32Clz, 28, 0x00000008);
648 TestInt32Unop(kExprI32Clz, 29, 0x00000004);
649 TestInt32Unop(kExprI32Clz, 30, 0x00000002);
650 TestInt32Unop(kExprI32Clz, 31, 0x00000001);
651 TestInt32Unop(kExprI32Clz, 32, 0x00000000);
652 }
653
654
655 TEST(Run_WasmInt32Ctz) {
656 TestInt32Unop(kExprI32Ctz, 32, 0x00000000);
657 TestInt32Unop(kExprI32Ctz, 31, 0x80000000);
658 TestInt32Unop(kExprI32Ctz, 30, 0x40000000);
659 TestInt32Unop(kExprI32Ctz, 29, 0x20000000);
660 TestInt32Unop(kExprI32Ctz, 28, 0x10000000);
661 TestInt32Unop(kExprI32Ctz, 27, 0xa8000000);
662 TestInt32Unop(kExprI32Ctz, 26, 0xf4000000);
663 TestInt32Unop(kExprI32Ctz, 25, 0x62000000);
664 TestInt32Unop(kExprI32Ctz, 24, 0x91000000);
665 TestInt32Unop(kExprI32Ctz, 23, 0xcd800000);
666 TestInt32Unop(kExprI32Ctz, 22, 0x09400000);
667 TestInt32Unop(kExprI32Ctz, 21, 0xaf200000);
668 TestInt32Unop(kExprI32Ctz, 20, 0xac100000);
669 TestInt32Unop(kExprI32Ctz, 19, 0xe0b80000);
670 TestInt32Unop(kExprI32Ctz, 18, 0x9ce40000);
671 TestInt32Unop(kExprI32Ctz, 17, 0xc7920000);
672 TestInt32Unop(kExprI32Ctz, 16, 0xb8f10000);
673 TestInt32Unop(kExprI32Ctz, 15, 0x3b9f8000);
674 TestInt32Unop(kExprI32Ctz, 14, 0xdb4c4000);
675 TestInt32Unop(kExprI32Ctz, 13, 0xe9a32000);
676 TestInt32Unop(kExprI32Ctz, 12, 0xfca61000);
677 TestInt32Unop(kExprI32Ctz, 11, 0x6c8a7800);
678 TestInt32Unop(kExprI32Ctz, 10, 0x8ce5a400);
679 TestInt32Unop(kExprI32Ctz, 9, 0xcb7d0200);
680 TestInt32Unop(kExprI32Ctz, 8, 0xcb4dc100);
681 TestInt32Unop(kExprI32Ctz, 7, 0xdfbec580);
682 TestInt32Unop(kExprI32Ctz, 6, 0x27a9db40);
683 TestInt32Unop(kExprI32Ctz, 5, 0xde3bcb20);
684 TestInt32Unop(kExprI32Ctz, 4, 0xd7e8a610);
685 TestInt32Unop(kExprI32Ctz, 3, 0x9afdbc88);
686 TestInt32Unop(kExprI32Ctz, 2, 0x9afdbc84);
687 TestInt32Unop(kExprI32Ctz, 1, 0x9afdbc82);
688 TestInt32Unop(kExprI32Ctz, 0, 0x9afdbc81);
689 }
690
691
692 TEST(Run_WasmInt32Popcnt) {
693 TestInt32Unop(kExprI32Popcnt, 32, 0xffffffff);
694 TestInt32Unop(kExprI32Popcnt, 0, 0x00000000);
695 TestInt32Unop(kExprI32Popcnt, 1, 0x00008000);
696 TestInt32Unop(kExprI32Popcnt, 13, 0x12345678);
697 TestInt32Unop(kExprI32Popcnt, 19, 0xfedcba09);
698 }
699
700
701 #if WASM_64
702 void TestInt64Binop(WasmOpcode opcode, int64_t expected, int64_t a, int64_t b) {
703 if (!WasmOpcodes::IsSupported(opcode)) return;
704 {
705 WasmRunner<int64_t> r;
706 // return K op K
707 BUILD(r, WASM_BINOP(opcode, WASM_I64(a), WASM_I64(b)));
708 CHECK_EQ(expected, r.Call());
709 }
710 {
711 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
712 // return a op b
713 BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
714 CHECK_EQ(expected, r.Call(a, b));
715 }
716 }
717
718
719 void TestInt64Cmp(WasmOpcode opcode, int64_t expected, int64_t a, int64_t b) {
720 if (!WasmOpcodes::IsSupported(opcode)) return;
721 {
722 WasmRunner<int32_t> r;
723 // return K op K
724 BUILD(r, WASM_BINOP(opcode, WASM_I64(a), WASM_I64(b)));
725 CHECK_EQ(expected, r.Call());
726 }
727 {
728 WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
729 // return a op b
730 BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
731 CHECK_EQ(expected, r.Call(a, b));
732 }
733 }
734
735
736 TEST(Run_WasmInt64Binops) {
737 // TODO(titzer): real 64-bit numbers
738 TestInt64Binop(kExprI64Add, 8888888888888LL, 3333333333333LL,
739 5555555555555LL);
740 TestInt64Binop(kExprI64Sub, -111111111111LL, 777777777777LL, 888888888888LL);
741 TestInt64Binop(kExprI64Mul, 65130756, 88734, 734);
742 TestInt64Binop(kExprI64DivS, -66, -4777344, 72384);
743 TestInt64Binop(kExprI64DivU, 805306368, 0xF0000000, 5);
744 TestInt64Binop(kExprI64RemS, -3, -3003, 1000);
745 TestInt64Binop(kExprI64RemU, 4, 4004, 1000);
746 TestInt64Binop(kExprI64And, 0xEE, 0xFFEE, 0xFF0000FF);
747 TestInt64Binop(kExprI64Ior, 0xF0FF00FF, 0xF0F000EE, 0x000F0011);
748 TestInt64Binop(kExprI64Xor, 0xABCDEF01, 0xABCDEFFF, 0xFE);
749 TestInt64Binop(kExprI64Shl, 0xA0000000, 0xA, 28);
750 TestInt64Binop(kExprI64ShrU, 0x0700001000123456LL, 0x7000010001234567LL, 4);
751 TestInt64Binop(kExprI64ShrS, 0xFF00000000000000LL, 0x8000000000000000LL, 7);
752 TestInt64Cmp(kExprI64Eq, 1, -9999, -9999);
753 TestInt64Cmp(kExprI64Ne, 1, -9199, -9999);
754 TestInt64Cmp(kExprI64LtS, 1, -4, 4);
755 TestInt64Cmp(kExprI64LeS, 0, -2, -3);
756 TestInt64Cmp(kExprI64LtU, 1, 0, -6);
757 TestInt64Cmp(kExprI64LeU, 1, 98978, 0xF0000000);
758 }
759
760
761 TEST(Run_WasmInt64Clz) {
762 struct {
763 int64_t expected;
764 uint64_t input;
765 } values[] = {{0, 0x8000100000000000}, {1, 0x4000050000000000},
766 {2, 0x2000030000000000}, {3, 0x1000000300000000},
767 {4, 0x0805000000000000}, {5, 0x0400600000000000},
768 {6, 0x0200000000000000}, {7, 0x010000a000000000},
769 {8, 0x00800c0000000000}, {9, 0x0040000000000000},
770 {10, 0x0020000d00000000}, {11, 0x00100f0000000000},
771 {12, 0x0008000000000000}, {13, 0x0004100000000000},
772 {14, 0x0002002000000000}, {15, 0x0001030000000000},
773 {16, 0x0000804000000000}, {17, 0x0000400500000000},
774 {18, 0x0000205000000000}, {19, 0x0000170000000000},
775 {20, 0x0000087000000000}, {21, 0x0000040500000000},
776 {22, 0x0000020300000000}, {23, 0x0000010100000000},
777 {24, 0x0000008900000000}, {25, 0x0000004100000000},
778 {26, 0x0000002200000000}, {27, 0x0000001300000000},
779 {28, 0x0000000800000000}, {29, 0x0000000400000000},
780 {30, 0x0000000200000000}, {31, 0x0000000100000000},
781 {32, 0x0000000080001000}, {33, 0x0000000040000500},
782 {34, 0x0000000020000300}, {35, 0x0000000010000003},
783 {36, 0x0000000008050000}, {37, 0x0000000004006000},
784 {38, 0x0000000002000000}, {39, 0x00000000010000a0},
785 {40, 0x0000000000800c00}, {41, 0x0000000000400000},
786 {42, 0x000000000020000d}, {43, 0x0000000000100f00},
787 {44, 0x0000000000080000}, {45, 0x0000000000041000},
788 {46, 0x0000000000020020}, {47, 0x0000000000010300},
789 {48, 0x0000000000008040}, {49, 0x0000000000004005},
790 {50, 0x0000000000002050}, {51, 0x0000000000001700},
791 {52, 0x0000000000000870}, {53, 0x0000000000000405},
792 {54, 0x0000000000000203}, {55, 0x0000000000000101},
793 {56, 0x0000000000000089}, {57, 0x0000000000000041},
794 {58, 0x0000000000000022}, {59, 0x0000000000000013},
795 {60, 0x0000000000000008}, {61, 0x0000000000000004},
796 {62, 0x0000000000000002}, {63, 0x0000000000000001},
797 {64, 0x0000000000000000}};
798
799 WasmRunner<int64_t> r(MachineType::Uint64());
800 BUILD(r, WASM_I64_CLZ(WASM_GET_LOCAL(0)));
801 for (size_t i = 0; i < arraysize(values); i++) {
802 CHECK_EQ(values[i].expected, r.Call(values[i].input));
803 }
804 }
805
806
807 TEST(Run_WasmInt64Ctz) {
808 struct {
809 int64_t expected;
810 uint64_t input;
811 } values[] = {{64, 0x0000000000000000}, {63, 0x8000000000000000},
812 {62, 0x4000000000000000}, {61, 0x2000000000000000},
813 {60, 0x1000000000000000}, {59, 0xa800000000000000},
814 {58, 0xf400000000000000}, {57, 0x6200000000000000},
815 {56, 0x9100000000000000}, {55, 0xcd80000000000000},
816 {54, 0x0940000000000000}, {53, 0xaf20000000000000},
817 {52, 0xac10000000000000}, {51, 0xe0b8000000000000},
818 {50, 0x9ce4000000000000}, {49, 0xc792000000000000},
819 {48, 0xb8f1000000000000}, {47, 0x3b9f800000000000},
820 {46, 0xdb4c400000000000}, {45, 0xe9a3200000000000},
821 {44, 0xfca6100000000000}, {43, 0x6c8a780000000000},
822 {42, 0x8ce5a40000000000}, {41, 0xcb7d020000000000},
823 {40, 0xcb4dc10000000000}, {39, 0xdfbec58000000000},
824 {38, 0x27a9db4000000000}, {37, 0xde3bcb2000000000},
825 {36, 0xd7e8a61000000000}, {35, 0x9afdbc8800000000},
826 {34, 0x9afdbc8400000000}, {33, 0x9afdbc8200000000},
827 {32, 0x9afdbc8100000000}, {31, 0x0000000080000000},
828 {30, 0x0000000040000000}, {29, 0x0000000020000000},
829 {28, 0x0000000010000000}, {27, 0x00000000a8000000},
830 {26, 0x00000000f4000000}, {25, 0x0000000062000000},
831 {24, 0x0000000091000000}, {23, 0x00000000cd800000},
832 {22, 0x0000000009400000}, {21, 0x00000000af200000},
833 {20, 0x00000000ac100000}, {19, 0x00000000e0b80000},
834 {18, 0x000000009ce40000}, {17, 0x00000000c7920000},
835 {16, 0x00000000b8f10000}, {15, 0x000000003b9f8000},
836 {14, 0x00000000db4c4000}, {13, 0x00000000e9a32000},
837 {12, 0x00000000fca61000}, {11, 0x000000006c8a7800},
838 {10, 0x000000008ce5a400}, {9, 0x00000000cb7d0200},
839 {8, 0x00000000cb4dc100}, {7, 0x00000000dfbec580},
840 {6, 0x0000000027a9db40}, {5, 0x00000000de3bcb20},
841 {4, 0x00000000d7e8a610}, {3, 0x000000009afdbc88},
842 {2, 0x000000009afdbc84}, {1, 0x000000009afdbc82},
843 {0, 0x000000009afdbc81}};
844
845 WasmRunner<int64_t> r(MachineType::Uint64());
846 BUILD(r, WASM_I64_CTZ(WASM_GET_LOCAL(0)));
847 for (size_t i = 0; i < arraysize(values); i++) {
848 CHECK_EQ(values[i].expected, r.Call(values[i].input));
849 }
850 }
851
852
853 TEST(Run_WasmInt64Popcnt) {
854 struct {
855 int64_t expected;
856 uint64_t input;
857 } values[] = {{64, 0xffffffffffffffff},
858 {0, 0x0000000000000000},
859 {2, 0x0000080000008000},
860 {26, 0x1123456782345678},
861 {38, 0xffedcba09edcba09}};
862
863 WasmRunner<int64_t> r(MachineType::Uint64());
864 BUILD(r, WASM_I64_POPCNT(WASM_GET_LOCAL(0)));
865 for (size_t i = 0; i < arraysize(values); i++) {
866 CHECK_EQ(values[i].expected, r.Call(values[i].input));
867 }
868 }
869
870
871 #endif
872
873 TEST(Run_WASM_Int32DivS_trap) {
874 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
875 BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
876 CHECK_EQ(0, r.Call(0, 100));
877 CHECK_TRAP(r.Call(100, 0));
878 CHECK_TRAP(r.Call(-1001, 0));
879 CHECK_TRAP(r.Call(std::numeric_limits<int32_t>::min(), -1));
880 CHECK_TRAP(r.Call(std::numeric_limits<int32_t>::min(), 0));
881 }
882
883
884 TEST(Run_WASM_Int32RemS_trap) {
885 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
886 BUILD(r, WASM_I32_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
887 CHECK_EQ(33, r.Call(133, 100));
888 CHECK_EQ(0, r.Call(std::numeric_limits<int32_t>::min(), -1));
889 CHECK_TRAP(r.Call(100, 0));
890 CHECK_TRAP(r.Call(-1001, 0));
891 CHECK_TRAP(r.Call(std::numeric_limits<int32_t>::min(), 0));
892 }
893
894
895 TEST(Run_WASM_Int32DivU_trap) {
896 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
897 BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
898 CHECK_EQ(0, r.Call(0, 100));
899 CHECK_EQ(0, r.Call(std::numeric_limits<int32_t>::min(), -1));
900 CHECK_TRAP(r.Call(100, 0));
901 CHECK_TRAP(r.Call(-1001, 0));
902 CHECK_TRAP(r.Call(std::numeric_limits<int32_t>::min(), 0));
903 }
904
905
906 TEST(Run_WASM_Int32RemU_trap) {
907 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
908 BUILD(r, WASM_I32_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
909 CHECK_EQ(17, r.Call(217, 100));
910 CHECK_TRAP(r.Call(100, 0));
911 CHECK_TRAP(r.Call(-1001, 0));
912 CHECK_TRAP(r.Call(std::numeric_limits<int32_t>::min(), 0));
913 CHECK_EQ(std::numeric_limits<int32_t>::min(),
914 r.Call(std::numeric_limits<int32_t>::min(), -1));
915 }
916
917
918 TEST(Run_WASM_Int32DivS_byzero_const) {
919 for (int8_t denom = -2; denom < 8; denom++) {
920 WasmRunner<int32_t> r(MachineType::Int32());
921 BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_I8(denom)));
922 for (int32_t val = -7; val < 8; val++) {
923 if (denom == 0) {
924 CHECK_TRAP(r.Call(val));
925 } else {
926 CHECK_EQ(val / denom, r.Call(val));
927 }
928 }
929 }
930 }
931
932
933 TEST(Run_WASM_Int32DivU_byzero_const) {
934 for (uint32_t denom = 0xfffffffe; denom < 8; denom++) {
935 WasmRunner<uint32_t> r(MachineType::Uint32());
936 BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_I32(denom)));
937
938 for (uint32_t val = 0xfffffff0; val < 8; val++) {
939 if (denom == 0) {
940 CHECK_TRAP(r.Call(val));
941 } else {
942 CHECK_EQ(val / denom, r.Call(val));
943 }
944 }
945 }
946 }
947
948
949 TEST(Run_WASM_Int32DivS_trap_effect) {
950 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
951 TestingModule module;
952 module.AddMemoryElems<int32_t>(8);
953 r.env()->module = &module;
954
955 BUILD(r,
956 WASM_IF_ELSE(WASM_GET_LOCAL(0),
957 WASM_I32_DIVS(WASM_STORE_MEM(MachineType::Int8(),
958 WASM_ZERO, WASM_GET_LOCAL(0)),
959 WASM_GET_LOCAL(1)),
960 WASM_I32_DIVS(WASM_STORE_MEM(MachineType::Int8(),
961 WASM_ZERO, WASM_GET_LOCAL(0)),
962 WASM_GET_LOCAL(1))));
963 CHECK_EQ(0, r.Call(0, 100));
964 CHECK_TRAP(r.Call(8, 0));
965 CHECK_TRAP(r.Call(4, 0));
966 CHECK_TRAP(r.Call(0, 0));
967 }
968
969
970 #if WASM_64
971 #define as64(x) static_cast<int64_t>(x)
972 TEST(Run_WASM_Int64DivS_trap) {
973 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
974 BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
975 CHECK_EQ(0, r.Call(as64(0), as64(100)));
976 CHECK_TRAP(r.Call(as64(100), as64(0)));
977 CHECK_TRAP(r.Call(as64(-1001), as64(0)));
978 CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(-1)));
979 CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(0)));
980 }
981
982
983 TEST(Run_WASM_Int64RemS_trap) {
984 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
985 BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
986 CHECK_EQ(33, r.Call(as64(133), as64(100)));
987 CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), as64(-1)));
988 CHECK_TRAP(r.Call(as64(100), as64(0)));
989 CHECK_TRAP(r.Call(as64(-1001), as64(0)));
990 CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(0)));
991 }
992
993
994 TEST(Run_WASM_Int64DivU_trap) {
995 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
996 BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
997 CHECK_EQ(0, r.Call(as64(0), as64(100)));
998 CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), as64(-1)));
999 CHECK_TRAP(r.Call(as64(100), as64(0)));
1000 CHECK_TRAP(r.Call(as64(-1001), as64(0)));
1001 CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(0)));
1002 }
1003
1004
1005 TEST(Run_WASM_Int64RemU_trap) {
1006 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
1007 BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
1008 CHECK_EQ(17, r.Call(as64(217), as64(100)));
1009 CHECK_TRAP(r.Call(as64(100), as64(0)));
1010 CHECK_TRAP(r.Call(as64(-1001), as64(0)));
1011 CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(0)));
1012 CHECK_EQ(std::numeric_limits<int64_t>::min(),
1013 r.Call(std::numeric_limits<int64_t>::min(), as64(-1)));
1014 }
1015
1016
1017 TEST(Run_WASM_Int64DivS_byzero_const) {
1018 for (int8_t denom = -2; denom < 8; denom++) {
1019 WasmRunner<int64_t> r(MachineType::Int64());
1020 BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_I64(denom)));
1021 for (int64_t val = -7; val < 8; val++) {
1022 if (denom == 0) {
1023 CHECK_TRAP(r.Call(val));
1024 } else {
1025 CHECK_EQ(val / denom, r.Call(val));
1026 }
1027 }
1028 }
1029 }
1030
1031
1032 TEST(Run_WASM_Int64DivU_byzero_const) {
1033 for (uint64_t denom = 0xfffffffffffffffe; denom < 8; denom++) {
1034 WasmRunner<uint64_t> r(MachineType::Uint64());
1035 BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_I64(denom)));
1036
1037 for (uint64_t val = 0xfffffffffffffff0; val < 8; val++) {
1038 if (denom == 0) {
1039 CHECK_TRAP(r.Call(val));
1040 } else {
1041 CHECK_EQ(val / denom, r.Call(val));
1042 }
1043 }
1044 }
1045 }
1046 #endif
1047
1048
1049 void TestFloat32Binop(WasmOpcode opcode, int32_t expected, float a, float b) {
1050 WasmRunner<int32_t> r;
1051 // return K op K
1052 BUILD(r, WASM_BINOP(opcode, WASM_F32(a), WASM_F32(b)));
1053 CHECK_EQ(expected, r.Call());
1054 // TODO(titzer): test float parameters
1055 }
1056
1057
1058 void TestFloat32BinopWithConvert(WasmOpcode opcode, int32_t expected, float a,
1059 float b) {
1060 WasmRunner<int32_t> r;
1061 // return int(K op K)
1062 BUILD(r, WASM_I32_SCONVERT_F32(WASM_BINOP(opcode, WASM_F32(a), WASM_F32(b))));
1063 CHECK_EQ(expected, r.Call());
1064 // TODO(titzer): test float parameters
1065 }
1066
1067
1068 void TestFloat32UnopWithConvert(WasmOpcode opcode, int32_t expected, float a) {
1069 WasmRunner<int32_t> r;
1070 // return int(K op K)
1071 BUILD(r, WASM_I32_SCONVERT_F32(WASM_UNOP(opcode, WASM_F32(a))));
1072 CHECK_EQ(expected, r.Call());
1073 // TODO(titzer): test float parameters
1074 }
1075
1076
1077 void TestFloat64Binop(WasmOpcode opcode, int32_t expected, double a, double b) {
1078 WasmRunner<int32_t> r;
1079 // return K op K
1080 BUILD(r, WASM_BINOP(opcode, WASM_F64(a), WASM_F64(b)));
1081 CHECK_EQ(expected, r.Call());
1082 // TODO(titzer): test double parameters
1083 }
1084
1085
1086 void TestFloat64BinopWithConvert(WasmOpcode opcode, int32_t expected, double a,
1087 double b) {
1088 WasmRunner<int32_t> r;
1089 // return int(K op K)
1090 BUILD(r, WASM_I32_SCONVERT_F64(WASM_BINOP(opcode, WASM_F64(a), WASM_F64(b))));
1091 CHECK_EQ(expected, r.Call());
1092 // TODO(titzer): test double parameters
1093 }
1094
1095
1096 void TestFloat64UnopWithConvert(WasmOpcode opcode, int32_t expected, double a) {
1097 WasmRunner<int32_t> r;
1098 // return int(K op K)
1099 BUILD(r, WASM_I32_SCONVERT_F64(WASM_UNOP(opcode, WASM_F64(a))));
1100 CHECK_EQ(expected, r.Call());
1101 // TODO(titzer): test float parameters
1102 }
1103
1104
1105 TEST(Run_WasmFloat32Binops) {
1106 TestFloat32Binop(kExprF32Eq, 1, 8.125, 8.125);
1107 TestFloat32Binop(kExprF32Ne, 1, 8.125, 8.127);
1108 TestFloat32Binop(kExprF32Lt, 1, -9.5, -9);
1109 TestFloat32Binop(kExprF32Le, 1, -1111, -1111);
1110 TestFloat32Binop(kExprF32Gt, 1, -9, -9.5);
1111 TestFloat32Binop(kExprF32Ge, 1, -1111, -1111);
1112
1113 TestFloat32BinopWithConvert(kExprF32Add, 10, 3.5, 6.5);
1114 TestFloat32BinopWithConvert(kExprF32Sub, 2, 44.5, 42.5);
1115 TestFloat32BinopWithConvert(kExprF32Mul, -66, -132.1, 0.5);
1116 TestFloat32BinopWithConvert(kExprF32Div, 11, 22.1, 2);
1117 }
1118
1119
1120 TEST(Run_WasmFloat32Unops) {
1121 TestFloat32UnopWithConvert(kExprF32Abs, 8, 8.125);
1122 TestFloat32UnopWithConvert(kExprF32Abs, 9, -9.125);
1123 TestFloat32UnopWithConvert(kExprF32Neg, -213, 213.125);
1124 TestFloat32UnopWithConvert(kExprF32Sqrt, 12, 144.4);
1125 }
1126
1127
1128 TEST(Run_WasmFloat64Binops) {
1129 TestFloat64Binop(kExprF64Eq, 1, 16.25, 16.25);
1130 TestFloat64Binop(kExprF64Ne, 1, 16.25, 16.15);
1131 TestFloat64Binop(kExprF64Lt, 1, -32.4, 11.7);
1132 TestFloat64Binop(kExprF64Le, 1, -88.9, -88.9);
1133 TestFloat64Binop(kExprF64Gt, 1, 11.7, -32.4);
1134 TestFloat64Binop(kExprF64Ge, 1, -88.9, -88.9);
1135
1136 TestFloat64BinopWithConvert(kExprF64Add, 100, 43.5, 56.5);
1137 TestFloat64BinopWithConvert(kExprF64Sub, 200, 12200.1, 12000.1);
1138 TestFloat64BinopWithConvert(kExprF64Mul, -33, 134, -0.25);
1139 TestFloat64BinopWithConvert(kExprF64Div, -1111, -2222.3, 2);
1140 }
1141
1142
1143 TEST(Run_WasmFloat64Unops) {
1144 TestFloat64UnopWithConvert(kExprF64Abs, 108, 108.125);
1145 TestFloat64UnopWithConvert(kExprF64Abs, 209, -209.125);
1146 TestFloat64UnopWithConvert(kExprF64Neg, -209, 209.125);
1147 TestFloat64UnopWithConvert(kExprF64Sqrt, 13, 169.4);
1148 }
1149
1150
1151 TEST(Run_Wasm_IfElse_P) {
1152 WasmRunner<int32_t> r(MachineType::Int32());
1153 // if (p0) return 11; else return 22;
1154 BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0), // --
1155 WASM_I8(11), // --
1156 WASM_I8(22))); // --
1157 FOR_INT32_INPUTS(i) {
1158 int32_t expected = *i ? 11 : 22;
1159 CHECK_EQ(expected, r.Call(*i));
1160 }
1161 }
1162
1163
1164 TEST(Run_Wasm_IfElse_Unreachable1) {
1165 WasmRunner<int32_t> r;
1166 // if (0) unreachable; else return 22;
1167 BUILD(r, WASM_IF_ELSE(WASM_ZERO, // --
1168 WASM_UNREACHABLE, // --
1169 WASM_I8(27))); // --
1170 CHECK_EQ(27, r.Call());
1171 }
1172
1173
1174 TEST(Run_Wasm_Return12) {
1175 WasmRunner<int32_t> r;
1176
1177 BUILD(r, WASM_RETURN(WASM_I8(12)));
1178 CHECK_EQ(12, r.Call());
1179 }
1180
1181
1182 TEST(Run_Wasm_Return17) {
1183 WasmRunner<int32_t> r;
1184
1185 BUILD(r, WASM_BLOCK(1, WASM_RETURN(WASM_I8(17))));
1186 CHECK_EQ(17, r.Call());
1187 }
1188
1189
1190 TEST(Run_Wasm_Return_I32) {
1191 WasmRunner<int32_t> r(MachineType::Int32());
1192
1193 BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0)));
1194
1195 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
1196 }
1197
1198
1199 #if WASM_64
1200 TEST(Run_Wasm_Return_I64) {
1201 WasmRunner<int64_t> r(MachineType::Int64());
1202
1203 BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0)));
1204
1205 FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
1206 }
1207 #endif
1208
1209
1210 TEST(Run_Wasm_Return_F32) {
1211 WasmRunner<float> r(MachineType::Float32());
1212
1213 BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0)));
1214
1215 FOR_FLOAT32_INPUTS(i) {
1216 float expect = *i;
1217 float result = r.Call(expect);
1218 if (std::isnan(expect)) {
1219 CHECK(std::isnan(result));
1220 } else {
1221 CHECK_EQ(expect, result);
1222 }
1223 }
1224 }
1225
1226
1227 TEST(Run_Wasm_Return_F64) {
1228 WasmRunner<double> r(MachineType::Float64());
1229
1230 BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0)));
1231
1232 FOR_FLOAT64_INPUTS(i) {
1233 double expect = *i;
1234 double result = r.Call(expect);
1235 if (std::isnan(expect)) {
1236 CHECK(std::isnan(result));
1237 } else {
1238 CHECK_EQ(expect, result);
1239 }
1240 }
1241 }
1242
1243
1244 TEST(Run_Wasm_Select) {
1245 WasmRunner<int32_t> r(MachineType::Int32());
1246 // return select(a, 11, 22);
1247 BUILD(r, WASM_SELECT(WASM_GET_LOCAL(0), WASM_I8(11), WASM_I8(22)));
1248 FOR_INT32_INPUTS(i) {
1249 int32_t expected = *i ? 11 : 22;
1250 CHECK_EQ(expected, r.Call(*i));
1251 }
1252 }
1253
1254
1255 TEST(Run_Wasm_Select_strict1) {
1256 WasmRunner<int32_t> r(MachineType::Int32());
1257 // select(a, a = 11, 22); return a
1258 BUILD(r,
1259 WASM_BLOCK(2, WASM_SELECT(WASM_GET_LOCAL(0),
1260 WASM_SET_LOCAL(0, WASM_I8(11)), WASM_I8(22)),
1261 WASM_GET_LOCAL(0)));
1262 FOR_INT32_INPUTS(i) { CHECK_EQ(11, r.Call(*i)); }
1263 }
1264
1265
1266 TEST(Run_Wasm_Select_strict2) {
1267 WasmRunner<int32_t> r(MachineType::Int32());
1268 // select(a, 11, a = 22); return a;
1269 BUILD(r, WASM_BLOCK(2, WASM_SELECT(WASM_GET_LOCAL(0), WASM_I8(11),
1270 WASM_SET_LOCAL(0, WASM_I8(22))),
1271 WASM_GET_LOCAL(0)));
1272 FOR_INT32_INPUTS(i) { CHECK_EQ(22, r.Call(*i)); }
1273 }
1274
1275
1276 TEST(Run_Wasm_BrIf_strict) {
1277 WasmRunner<int32_t> r(MachineType::Int32());
1278 BUILD(r, WASM_BLOCK(
1279 2, WASM_BLOCK(1, WASM_BRV_IF(0, WASM_GET_LOCAL(0),
1280 WASM_SET_LOCAL(0, WASM_I8(99)))),
1281 WASM_GET_LOCAL(0)));
1282
1283 FOR_INT32_INPUTS(i) { CHECK_EQ(99, r.Call(*i)); }
1284 }
1285
1286
1287 TEST(Run_Wasm_TableSwitch1) {
1288 WasmRunner<int32_t> r(MachineType::Int32());
1289 BUILD(r, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)),
1290 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(93))));
1291 FOR_INT32_INPUTS(i) { CHECK_EQ(93, r.Call(*i)); }
1292 }
1293
1294
1295 TEST(Run_Wasm_TableSwitch_br) {
1296 WasmRunner<int32_t> r(MachineType::Int32());
1297 BUILD(r, WASM_TABLESWITCH_OP(1, 2, WASM_CASE_BR(0), WASM_CASE(0)),
1298 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(91))),
1299 WASM_I8(99));
1300 CHECK_EQ(99, r.Call(0));
1301 CHECK_EQ(91, r.Call(1));
1302 CHECK_EQ(91, r.Call(2));
1303 CHECK_EQ(91, r.Call(3));
1304 }
1305
1306
1307 TEST(Run_Wasm_TableSwitch_br2) {
1308 WasmRunner<int32_t> r(MachineType::Int32());
1309 BUILD(r, WASM_BLOCK(
1310 2, WASM_BLOCK(2, WASM_TABLESWITCH_OP(
1311 1, 4, WASM_CASE_BR(0), WASM_CASE_BR(1),
1312 WASM_CASE_BR(2), WASM_CASE(0)),
1313 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0),
1314 WASM_RETURN(WASM_I8(85))),
1315 WASM_RETURN(WASM_I8(86))),
1316 WASM_RETURN(WASM_I8(87))),
1317 WASM_I8(88));
1318 CHECK_EQ(86, r.Call(0));
1319 CHECK_EQ(87, r.Call(1));
1320 CHECK_EQ(88, r.Call(2));
1321 CHECK_EQ(85, r.Call(3));
1322 CHECK_EQ(85, r.Call(4));
1323 CHECK_EQ(85, r.Call(5));
1324 }
1325
1326
1327 TEST(Run_Wasm_TableSwitch2) {
1328 WasmRunner<int32_t> r(MachineType::Int32());
1329 BUILD(r, WASM_TABLESWITCH_OP(2, 2, WASM_CASE(0), WASM_CASE(1)),
1330 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(91)),
1331 WASM_RETURN(WASM_I8(92))));
1332 FOR_INT32_INPUTS(i) {
1333 int32_t expected = *i == 0 ? 91 : 92;
1334 CHECK_EQ(expected, r.Call(*i));
1335 }
1336 }
1337
1338
1339 TEST(Run_Wasm_TableSwitch2b) {
1340 WasmRunner<int32_t> r(MachineType::Int32());
1341 BUILD(r, WASM_TABLESWITCH_OP(2, 2, WASM_CASE(1), WASM_CASE(0)),
1342 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(81)),
1343 WASM_RETURN(WASM_I8(82))));
1344 FOR_INT32_INPUTS(i) {
1345 int32_t expected = *i == 0 ? 82 : 81;
1346 CHECK_EQ(expected, r.Call(*i));
1347 }
1348 }
1349
1350
1351 TEST(Run_Wasm_TableSwitch4) {
1352 for (int i = 0; i < 4; i++) {
1353 const uint16_t br = 0x8000u;
1354 uint16_t c = 0;
1355 uint16_t cases[] = {i == 0 ? br : c++, i == 1 ? br : c++, i == 2 ? br : c++,
1356 i == 3 ? br : c++};
1357 byte code[] = {
1358 WASM_BLOCK(1, WASM_TABLESWITCH_OP(
1359 3, 4, WASM_CASE(cases[0]), WASM_CASE(cases[1]),
1360 WASM_CASE(cases[2]), WASM_CASE(cases[3])),
1361 WASM_TABLESWITCH_BODY(
1362 WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(71)),
1363 WASM_RETURN(WASM_I8(72)), WASM_RETURN(WASM_I8(73)))),
1364 WASM_RETURN(WASM_I8(74))};
1365
1366 WasmRunner<int32_t> r(MachineType::Int32());
1367 r.Build(code, code + arraysize(code));
1368
1369 FOR_INT32_INPUTS(i) {
1370 int index = (*i < 0 || *i > 3) ? 3 : *i;
1371 int32_t expected = 71 + cases[index];
1372 if (expected >= 0x8000) expected = 74;
1373 CHECK_EQ(expected, r.Call(*i));
1374 }
1375 }
1376 }
1377
1378
1379 TEST(Run_Wasm_TableSwitch4b) {
1380 for (int a = 0; a < 2; a++) {
1381 for (int b = 0; b < 2; b++) {
1382 for (int c = 0; c < 2; c++) {
1383 for (int d = 0; d < 2; d++) {
1384 if (a + b + c + d == 0) continue;
1385 if (a + b + c + d == 4) continue;
1386
1387 byte code[] = {
1388 WASM_TABLESWITCH_OP(2, 4, WASM_CASE(a), WASM_CASE(b),
1389 WASM_CASE(c), WASM_CASE(d)),
1390 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(61)),
1391 WASM_RETURN(WASM_I8(62)))};
1392
1393 WasmRunner<int32_t> r(MachineType::Int32());
1394 r.Build(code, code + arraysize(code));
1395
1396 CHECK_EQ(61 + a, r.Call(0));
1397 CHECK_EQ(61 + b, r.Call(1));
1398 CHECK_EQ(61 + c, r.Call(2));
1399 CHECK_EQ(61 + d, r.Call(3));
1400 CHECK_EQ(61 + d, r.Call(4));
1401 }
1402 }
1403 }
1404 }
1405 }
1406
1407
1408 TEST(Run_Wasm_TableSwitch4_fallthru) {
1409 byte code[] = {
1410 WASM_TABLESWITCH_OP(4, 4, WASM_CASE(0), WASM_CASE(1), WASM_CASE(2),
1411 WASM_CASE(3)),
1412 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_INC_LOCAL_BY(1, 1),
1413 WASM_INC_LOCAL_BY(1, 2), WASM_INC_LOCAL_BY(1, 4),
1414 WASM_INC_LOCAL_BY(1, 8)),
1415 WASM_GET_LOCAL(1)};
1416
1417 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
1418 r.Build(code, code + arraysize(code));
1419
1420 CHECK_EQ(15, r.Call(0, 0));
1421 CHECK_EQ(14, r.Call(1, 0));
1422 CHECK_EQ(12, r.Call(2, 0));
1423 CHECK_EQ(8, r.Call(3, 0));
1424 CHECK_EQ(8, r.Call(4, 0));
1425
1426 CHECK_EQ(115, r.Call(0, 100));
1427 CHECK_EQ(114, r.Call(1, 100));
1428 CHECK_EQ(112, r.Call(2, 100));
1429 CHECK_EQ(108, r.Call(3, 100));
1430 CHECK_EQ(108, r.Call(4, 100));
1431 }
1432
1433
1434 TEST(Run_Wasm_TableSwitch4_fallthru_br) {
1435 byte code[] = {
1436 WASM_TABLESWITCH_OP(4, 4, WASM_CASE(0), WASM_CASE(1), WASM_CASE(2),
1437 WASM_CASE(3)),
1438 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_INC_LOCAL_BY(1, 1),
1439 WASM_BRV(0, WASM_INC_LOCAL_BY(1, 2)),
1440 WASM_INC_LOCAL_BY(1, 4),
1441 WASM_BRV(0, WASM_INC_LOCAL_BY(1, 8))),
1442 WASM_GET_LOCAL(1)};
1443
1444 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
1445 r.Build(code, code + arraysize(code));
1446
1447 CHECK_EQ(3, r.Call(0, 0));
1448 CHECK_EQ(2, r.Call(1, 0));
1449 CHECK_EQ(12, r.Call(2, 0));
1450 CHECK_EQ(8, r.Call(3, 0));
1451 CHECK_EQ(8, r.Call(4, 0));
1452
1453 CHECK_EQ(203, r.Call(0, 200));
1454 CHECK_EQ(202, r.Call(1, 200));
1455 CHECK_EQ(212, r.Call(2, 200));
1456 CHECK_EQ(208, r.Call(3, 200));
1457 CHECK_EQ(208, r.Call(4, 200));
1458 }
1459
1460
1461 TEST(Run_Wasm_F32ReinterpretI32) {
1462 WasmRunner<int32_t> r;
1463 TestingModule module;
1464 int32_t* memory = module.AddMemoryElems<int32_t>(8);
1465 r.env()->module = &module;
1466
1467 BUILD(r, WASM_I32_REINTERPRET_F32(
1468 WASM_LOAD_MEM(MachineType::Float32(), WASM_ZERO)));
1469
1470 FOR_INT32_INPUTS(i) {
1471 int32_t expected = *i;
1472 memory[0] = expected;
1473 CHECK_EQ(expected, r.Call());
1474 }
1475 }
1476
1477
1478 TEST(Run_Wasm_I32ReinterpretF32) {
1479 WasmRunner<int32_t> r(MachineType::Int32());
1480 TestingModule module;
1481 int32_t* memory = module.AddMemoryElems<int32_t>(8);
1482 r.env()->module = &module;
1483
1484 BUILD(r, WASM_BLOCK(
1485 2, WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO,
1486 WASM_F32_REINTERPRET_I32(WASM_GET_LOCAL(0))),
1487 WASM_I8(107)));
1488
1489 FOR_INT32_INPUTS(i) {
1490 int32_t expected = *i;
1491 CHECK_EQ(107, r.Call(expected));
1492 CHECK_EQ(expected, memory[0]);
1493 }
1494 }
1495
1496
1497 TEST(Run_Wasm_ReturnStore) {
1498 WasmRunner<int32_t> r;
1499 TestingModule module;
1500 int32_t* memory = module.AddMemoryElems<int32_t>(8);
1501 r.env()->module = &module;
1502
1503 BUILD(r, WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO,
1504 WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)));
1505
1506 FOR_INT32_INPUTS(i) {
1507 int32_t expected = *i;
1508 memory[0] = expected;
1509 CHECK_EQ(expected, r.Call());
1510 }
1511 }
1512
1513
1514 TEST(Run_Wasm_VoidReturn1) {
1515 WasmRunner<void> r;
1516 BUILD(r, kExprNop);
1517 r.Call();
1518 }
1519
1520
1521 TEST(Run_Wasm_VoidReturn2) {
1522 WasmRunner<void> r;
1523 BUILD(r, WASM_RETURN0);
1524 r.Call();
1525 }
1526
1527
1528 TEST(Run_Wasm_Block_If_P) {
1529 WasmRunner<int32_t> r(MachineType::Int32());
1530 // { if (p0) return 51; return 52; }
1531 BUILD(r, WASM_BLOCK(2, // --
1532 WASM_IF(WASM_GET_LOCAL(0), // --
1533 WASM_BRV(0, WASM_I8(51))), // --
1534 WASM_I8(52))); // --
1535 FOR_INT32_INPUTS(i) {
1536 int32_t expected = *i ? 51 : 52;
1537 CHECK_EQ(expected, r.Call(*i));
1538 }
1539 }
1540
1541
1542 TEST(Run_Wasm_Block_BrIf_P) {
1543 WasmRunner<int32_t> r(MachineType::Int32());
1544 BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(51)),
1545 WASM_I8(52)));
1546 FOR_INT32_INPUTS(i) {
1547 int32_t expected = *i ? 51 : 52;
1548 CHECK_EQ(expected, r.Call(*i));
1549 }
1550 }
1551
1552
1553 TEST(Run_Wasm_Block_IfElse_P_assign) {
1554 WasmRunner<int32_t> r(MachineType::Int32());
1555 // { if (p0) p0 = 71; else p0 = 72; return p0; }
1556 BUILD(r, WASM_BLOCK(2, // --
1557 WASM_IF_ELSE(WASM_GET_LOCAL(0), // --
1558 WASM_SET_LOCAL(0, WASM_I8(71)), // --
1559 WASM_SET_LOCAL(0, WASM_I8(72))), // --
1560 WASM_GET_LOCAL(0)));
1561 FOR_INT32_INPUTS(i) {
1562 int32_t expected = *i ? 71 : 72;
1563 CHECK_EQ(expected, r.Call(*i));
1564 }
1565 }
1566
1567
1568 TEST(Run_Wasm_Block_IfElse_P_return) {
1569 WasmRunner<int32_t> r(MachineType::Int32());
1570 // if (p0) return 81; else return 82;
1571 BUILD(r, // --
1572 WASM_IF_ELSE(WASM_GET_LOCAL(0), // --
1573 WASM_RETURN(WASM_I8(81)), // --
1574 WASM_RETURN(WASM_I8(82)))); // --
1575 FOR_INT32_INPUTS(i) {
1576 int32_t expected = *i ? 81 : 82;
1577 CHECK_EQ(expected, r.Call(*i));
1578 }
1579 }
1580
1581
1582 TEST(Run_Wasm_Block_If_P_assign) {
1583 WasmRunner<int32_t> r(MachineType::Int32());
1584 // { if (p0) p0 = 61; p0; }
1585 BUILD(r, WASM_BLOCK(
1586 2, WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_I8(61))),
1587 WASM_GET_LOCAL(0)));
1588 FOR_INT32_INPUTS(i) {
1589 int32_t expected = *i ? 61 : *i;
1590 CHECK_EQ(expected, r.Call(*i));
1591 }
1592 }
1593
1594
1595 TEST(Run_Wasm_ExprIf_P) {
1596 WasmRunner<int32_t> r(MachineType::Int32());
1597 // p0 ? 11 : 22;
1598 BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0), // --
1599 WASM_I8(11), // --
1600 WASM_I8(22))); // --
1601 FOR_INT32_INPUTS(i) {
1602 int32_t expected = *i ? 11 : 22;
1603 CHECK_EQ(expected, r.Call(*i));
1604 }
1605 }
1606
1607
1608 TEST(Run_Wasm_ExprIf_P_fallthru) {
1609 WasmRunner<int32_t> r(MachineType::Int32());
1610 // p0 ? 11 : 22;
1611 BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0), // --
1612 WASM_I8(11), // --
1613 WASM_I8(22))); // --
1614 FOR_INT32_INPUTS(i) {
1615 int32_t expected = *i ? 11 : 22;
1616 CHECK_EQ(expected, r.Call(*i));
1617 }
1618 }
1619
1620
1621 TEST(Run_Wasm_CountDown) {
1622 WasmRunner<int32_t> r(MachineType::Int32());
1623 BUILD(r,
1624 WASM_BLOCK(
1625 2, WASM_LOOP(
1626 1, WASM_IF(WASM_GET_LOCAL(0),
1627 WASM_BRV(0, WASM_SET_LOCAL(
1628 0, WASM_I32_SUB(WASM_GET_LOCAL(0),
1629 WASM_I8(1)))))),
1630 WASM_GET_LOCAL(0)));
1631 CHECK_EQ(0, r.Call(1));
1632 CHECK_EQ(0, r.Call(10));
1633 CHECK_EQ(0, r.Call(100));
1634 }
1635
1636
1637 TEST(Run_Wasm_CountDown_fallthru) {
1638 WasmRunner<int32_t> r(MachineType::Int32());
1639 BUILD(r,
1640 WASM_BLOCK(
1641 2, WASM_LOOP(3, WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)), WASM_BREAK(0)),
1642 WASM_SET_LOCAL(
1643 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(1))),
1644 WASM_CONTINUE(0)),
1645 WASM_GET_LOCAL(0)));
1646 CHECK_EQ(0, r.Call(1));
1647 CHECK_EQ(0, r.Call(10));
1648 CHECK_EQ(0, r.Call(100));
1649 }
1650
1651
1652 TEST(Run_Wasm_WhileCountDown) {
1653 WasmRunner<int32_t> r(MachineType::Int32());
1654 BUILD(r, WASM_BLOCK(
1655 2, WASM_WHILE(WASM_GET_LOCAL(0),
1656 WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0),
1657 WASM_I8(1)))),
1658 WASM_GET_LOCAL(0)));
1659 CHECK_EQ(0, r.Call(1));
1660 CHECK_EQ(0, r.Call(10));
1661 CHECK_EQ(0, r.Call(100));
1662 }
1663
1664
1665 TEST(Run_Wasm_Loop_if_break1) {
1666 WasmRunner<int32_t> r(MachineType::Int32());
1667 BUILD(r, WASM_BLOCK(2, WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(0)),
1668 WASM_SET_LOCAL(0, WASM_I8(99))),
1669 WASM_GET_LOCAL(0)));
1670 CHECK_EQ(99, r.Call(0));
1671 CHECK_EQ(3, r.Call(3));
1672 CHECK_EQ(10000, r.Call(10000));
1673 CHECK_EQ(-29, r.Call(-29));
1674 }
1675
1676
1677 TEST(Run_Wasm_Loop_if_break2) {
1678 WasmRunner<int32_t> r(MachineType::Int32());
1679 BUILD(r, WASM_BLOCK(2, WASM_LOOP(2, WASM_BR_IF(1, WASM_GET_LOCAL(0)),
1680 WASM_SET_LOCAL(0, WASM_I8(99))),
1681 WASM_GET_LOCAL(0)));
1682 CHECK_EQ(99, r.Call(0));
1683 CHECK_EQ(3, r.Call(3));
1684 CHECK_EQ(10000, r.Call(10000));
1685 CHECK_EQ(-29, r.Call(-29));
1686 }
1687
1688
1689 TEST(Run_Wasm_Loop_if_break_fallthru) {
1690 WasmRunner<int32_t> r(MachineType::Int32());
1691 BUILD(r, WASM_BLOCK(1, WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(1)),
1692 WASM_SET_LOCAL(0, WASM_I8(93)))),
1693 WASM_GET_LOCAL(0));
1694 CHECK_EQ(93, r.Call(0));
1695 CHECK_EQ(3, r.Call(3));
1696 CHECK_EQ(10001, r.Call(10001));
1697 CHECK_EQ(-22, r.Call(-22));
1698 }
1699
1700
1701 TEST(Run_Wasm_LoadMemI32) {
1702 WasmRunner<int32_t> r(MachineType::Int32());
1703 TestingModule module;
1704 int32_t* memory = module.AddMemoryElems<int32_t>(8);
1705 module.RandomizeMemory(1111);
1706 r.env()->module = &module;
1707
1708 BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(0)));
1709
1710 memory[0] = 99999999;
1711 CHECK_EQ(99999999, r.Call(0));
1712
1713 memory[0] = 88888888;
1714 CHECK_EQ(88888888, r.Call(0));
1715
1716 memory[0] = 77777777;
1717 CHECK_EQ(77777777, r.Call(0));
1718 }
1719
1720
1721 TEST(Run_Wasm_LoadMemI32_oob) {
1722 WasmRunner<int32_t> r(MachineType::Uint32());
1723 TestingModule module;
1724 int32_t* memory = module.AddMemoryElems<int32_t>(8);
1725 module.RandomizeMemory(1111);
1726 r.env()->module = &module;
1727
1728 BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
1729
1730 memory[0] = 88888888;
1731 CHECK_EQ(88888888, r.Call(0u));
1732 for (uint32_t offset = 29; offset < 40; offset++) {
1733 CHECK_TRAP(r.Call(offset));
1734 }
1735
1736 for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
1737 CHECK_TRAP(r.Call(offset));
1738 }
1739 }
1740
1741
1742 TEST(Run_Wasm_LoadMemI32_oob_asm) {
1743 WasmRunner<int32_t> r(MachineType::Uint32());
1744 TestingModule module;
1745 module.asm_js = true;
1746 int32_t* memory = module.AddMemoryElems<int32_t>(8);
1747 module.RandomizeMemory(1112);
1748 r.env()->module = &module;
1749
1750 BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
1751
1752 memory[0] = 999999;
1753 CHECK_EQ(999999, r.Call(0u));
1754 // TODO(titzer): offset 29-31 should also be OOB.
1755 for (uint32_t offset = 32; offset < 40; offset++) {
1756 CHECK_EQ(0, r.Call(offset));
1757 }
1758
1759 for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
1760 CHECK_EQ(0, r.Call(offset));
1761 }
1762 }
1763
1764
1765 TEST(Run_Wasm_LoadMem_offset_oob) {
1766 TestingModule module;
1767 module.AddMemoryElems<int32_t>(8);
1768
1769 static const MachineType machineTypes[] = {
1770 MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(),
1771 MachineType::Uint16(), MachineType::Int32(), MachineType::Uint32(),
1772 MachineType::Int64(), MachineType::Uint64(), MachineType::Float32(),
1773 MachineType::Float64()};
1774
1775 for (size_t m = 0; m < arraysize(machineTypes); m++) {
1776 module.RandomizeMemory(1116 + static_cast<int>(m));
1777 WasmRunner<int32_t> r(MachineType::Uint32());
1778 r.env()->module = &module;
1779 uint32_t boundary = 24 - WasmOpcodes::MemSize(machineTypes[m]);
1780
1781 BUILD(r, WASM_LOAD_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0)),
1782 WASM_ZERO);
1783
1784 CHECK_EQ(0, r.Call(boundary)); // in bounds.
1785
1786 for (uint32_t offset = boundary + 1; offset < boundary + 19; offset++) {
1787 CHECK_TRAP(r.Call(offset)); // out of bounds.
1788 }
1789 }
1790 }
1791
1792
1793 TEST(Run_Wasm_LoadMemI32_offset) {
1794 WasmRunner<int32_t> r(MachineType::Int32());
1795 TestingModule module;
1796 int32_t* memory = module.AddMemoryElems<int32_t>(4);
1797 module.RandomizeMemory(1111);
1798 r.env()->module = &module;
1799
1800 BUILD(r, WASM_LOAD_MEM_OFFSET(MachineType::Int32(), 4, WASM_GET_LOCAL(0)));
1801
1802 memory[0] = 66666666;
1803 memory[1] = 77777777;
1804 memory[2] = 88888888;
1805 memory[3] = 99999999;
1806 CHECK_EQ(77777777, r.Call(0));
1807 CHECK_EQ(88888888, r.Call(4));
1808 CHECK_EQ(99999999, r.Call(8));
1809
1810 memory[0] = 11111111;
1811 memory[1] = 22222222;
1812 memory[2] = 33333333;
1813 memory[3] = 44444444;
1814 CHECK_EQ(22222222, r.Call(0));
1815 CHECK_EQ(33333333, r.Call(4));
1816 CHECK_EQ(44444444, r.Call(8));
1817 }
1818
1819
1820 TEST(Run_Wasm_LoadMemI32_const_oob) {
1821 TestingModule module;
1822 const int kMemSize = 12;
1823 module.AddMemoryElems<byte>(kMemSize);
1824
1825 for (int offset = 0; offset < kMemSize + 5; offset++) {
1826 for (int index = 0; index < kMemSize + 5; index++) {
1827 WasmRunner<int32_t> r;
1828 r.env()->module = &module;
1829 module.RandomizeMemory();
1830
1831 BUILD(r,
1832 WASM_LOAD_MEM_OFFSET(MachineType::Int32(), offset, WASM_I8(index)));
1833
1834 if ((offset + index) <= (kMemSize - sizeof(int32_t))) {
1835 CHECK_EQ(module.raw_val_at<int32_t>(offset + index), r.Call());
1836 } else {
1837 CHECK_TRAP(r.Call());
1838 }
1839 }
1840 }
1841 }
1842
1843
1844 TEST(Run_Wasm_StoreMemI32_offset) {
1845 WasmRunner<int32_t> r(MachineType::Int32());
1846 const int32_t kWritten = 0xaabbccdd;
1847 TestingModule module;
1848 int32_t* memory = module.AddMemoryElems<int32_t>(4);
1849 r.env()->module = &module;
1850
1851 BUILD(r, WASM_STORE_MEM_OFFSET(MachineType::Int32(), 4, WASM_GET_LOCAL(0),
1852 WASM_I32(kWritten)));
1853
1854 for (int i = 0; i < 2; i++) {
1855 module.RandomizeMemory(1111);
1856 memory[0] = 66666666;
1857 memory[1] = 77777777;
1858 memory[2] = 88888888;
1859 memory[3] = 99999999;
1860 CHECK_EQ(kWritten, r.Call(i * 4));
1861 CHECK_EQ(66666666, memory[0]);
1862 CHECK_EQ(i == 0 ? kWritten : 77777777, memory[1]);
1863 CHECK_EQ(i == 1 ? kWritten : 88888888, memory[2]);
1864 CHECK_EQ(i == 2 ? kWritten : 99999999, memory[3]);
1865 }
1866 }
1867
1868
1869 TEST(Run_Wasm_StoreMem_offset_oob) {
1870 TestingModule module;
1871 byte* memory = module.AddMemoryElems<byte>(32);
1872
1873 static const MachineType machineTypes[] = {
1874 MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(),
1875 MachineType::Uint16(), MachineType::Int32(), MachineType::Uint32(),
1876 MachineType::Int64(), MachineType::Uint64(), MachineType::Float32(),
1877 MachineType::Float64()};
1878
1879 for (size_t m = 0; m < arraysize(machineTypes); m++) {
1880 module.RandomizeMemory(1119 + static_cast<int>(m));
1881 WasmRunner<int32_t> r(MachineType::Uint32());
1882 r.env()->module = &module;
1883
1884 BUILD(r, WASM_STORE_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0),
1885 WASM_LOAD_MEM(machineTypes[m], WASM_ZERO)),
1886 WASM_ZERO);
1887
1888 byte memsize = WasmOpcodes::MemSize(machineTypes[m]);
1889 uint32_t boundary = 24 - memsize;
1890 CHECK_EQ(0, r.Call(boundary)); // in bounds.
1891 CHECK_EQ(0, memcmp(&memory[0], &memory[8 + boundary], memsize));
1892
1893 for (uint32_t offset = boundary + 1; offset < boundary + 19; offset++) {
1894 CHECK_TRAP(r.Call(offset)); // out of bounds.
1895 }
1896 }
1897 }
1898
1899
1900 #if WASM_64
1901 TEST(Run_Wasm_F64ReinterpretI64) {
1902 WasmRunner<int64_t> r;
1903 TestingModule module;
1904 int64_t* memory = module.AddMemoryElems<int64_t>(8);
1905 r.env()->module = &module;
1906
1907 BUILD(r, WASM_I64_REINTERPRET_F64(
1908 WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO)));
1909
1910 FOR_INT32_INPUTS(i) {
1911 int64_t expected = static_cast<int64_t>(*i) * 0x300010001;
1912 memory[0] = expected;
1913 CHECK_EQ(expected, r.Call());
1914 }
1915 }
1916
1917
1918 TEST(Run_Wasm_I64ReinterpretF64) {
1919 WasmRunner<int64_t> r(MachineType::Int64());
1920 TestingModule module;
1921 int64_t* memory = module.AddMemoryElems<int64_t>(8);
1922 r.env()->module = &module;
1923
1924 BUILD(r, WASM_BLOCK(
1925 2, WASM_STORE_MEM(MachineType::Float64(), WASM_ZERO,
1926 WASM_F64_REINTERPRET_I64(WASM_GET_LOCAL(0))),
1927 WASM_GET_LOCAL(0)));
1928
1929 FOR_INT32_INPUTS(i) {
1930 int64_t expected = static_cast<int64_t>(*i) * 0x300010001;
1931 CHECK_EQ(expected, r.Call(expected));
1932 CHECK_EQ(expected, memory[0]);
1933 }
1934 }
1935
1936
1937 TEST(Run_Wasm_LoadMemI64) {
1938 WasmRunner<int64_t> r;
1939 TestingModule module;
1940 int64_t* memory = module.AddMemoryElems<int64_t>(8);
1941 module.RandomizeMemory(1111);
1942 r.env()->module = &module;
1943
1944 BUILD(r, WASM_LOAD_MEM(MachineType::Int64(), WASM_I8(0)));
1945
1946 memory[0] = 0xaabbccdd00112233LL;
1947 CHECK_EQ(0xaabbccdd00112233LL, r.Call());
1948
1949 memory[0] = 0x33aabbccdd001122LL;
1950 CHECK_EQ(0x33aabbccdd001122LL, r.Call());
1951
1952 memory[0] = 77777777;
1953 CHECK_EQ(77777777, r.Call());
1954 }
1955 #endif
1956
1957
1958 TEST(Run_Wasm_LoadMemI32_P) {
1959 const int kNumElems = 8;
1960 WasmRunner<int32_t> r(MachineType::Int32());
1961 TestingModule module;
1962 int32_t* memory = module.AddMemoryElems<int32_t>(kNumElems);
1963 module.RandomizeMemory(2222);
1964 r.env()->module = &module;
1965
1966 BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
1967
1968 for (int i = 0; i < kNumElems; i++) {
1969 CHECK_EQ(memory[i], r.Call(i * 4));
1970 }
1971 }
1972
1973
1974 TEST(Run_Wasm_MemI32_Sum) {
1975 WasmRunner<uint32_t> r(MachineType::Int32());
1976 const int kNumElems = 20;
1977 const byte kSum = r.AllocateLocal(kAstI32);
1978 TestingModule module;
1979 uint32_t* memory = module.AddMemoryElems<uint32_t>(kNumElems);
1980 r.env()->module = &module;
1981
1982 BUILD(r, WASM_BLOCK(
1983 2, WASM_WHILE(
1984 WASM_GET_LOCAL(0),
1985 WASM_BLOCK(
1986 2, WASM_SET_LOCAL(
1987 kSum, WASM_I32_ADD(
1988 WASM_GET_LOCAL(kSum),
1989 WASM_LOAD_MEM(MachineType::Int32(),
1990 WASM_GET_LOCAL(0)))),
1991 WASM_SET_LOCAL(
1992 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(4))))),
1993 WASM_GET_LOCAL(1)));
1994
1995 // Run 4 trials.
1996 for (int i = 0; i < 3; i++) {
1997 module.RandomizeMemory(i * 33);
1998 uint32_t expected = 0;
1999 for (size_t j = kNumElems - 1; j > 0; j--) {
2000 expected += memory[j];
2001 }
2002 uint32_t result = r.Call(static_cast<int>(4 * (kNumElems - 1)));
2003 CHECK_EQ(expected, result);
2004 }
2005 }
2006
2007
2008 TEST(Run_Wasm_CheckMachIntsZero) {
2009 WasmRunner<uint32_t> r(MachineType::Int32());
2010 const int kNumElems = 55;
2011 TestingModule module;
2012 module.AddMemoryElems<uint32_t>(kNumElems);
2013 r.env()->module = &module;
2014
2015 BUILD(r, kExprBlock, 2, kExprLoop, 1, kExprIf, kExprGetLocal, 0, kExprBr, 0,
2016 kExprIfElse, kExprI32LoadMem, 0, kExprGetLocal, 0, kExprBr, 2,
2017 kExprI8Const, 255, kExprSetLocal, 0, kExprI32Sub, kExprGetLocal, 0,
2018 kExprI8Const, 4, kExprI8Const, 0);
2019
2020 module.ZeroMemory();
2021 CHECK_EQ(0, r.Call((kNumElems - 1) * 4));
2022 }
2023
2024
2025 TEST(Run_Wasm_MemF32_Sum) {
2026 WasmRunner<int32_t> r(MachineType::Int32());
2027 const byte kSum = r.AllocateLocal(kAstF32);
2028 ModuleEnv module;
2029 const int kSize = 5;
2030 float buffer[kSize] = {-99.25, -888.25, -77.25, 66666.25, 5555.25};
2031 module.mem_start = reinterpret_cast<uintptr_t>(&buffer);
2032 module.mem_end = reinterpret_cast<uintptr_t>(&buffer[kSize]);
2033 r.env()->module = &module;
2034
2035 BUILD(r, WASM_BLOCK(
2036 3, WASM_WHILE(
2037 WASM_GET_LOCAL(0),
2038 WASM_BLOCK(
2039 2, WASM_SET_LOCAL(
2040 kSum, WASM_F32_ADD(
2041 WASM_GET_LOCAL(kSum),
2042 WASM_LOAD_MEM(MachineType::Float32(),
2043 WASM_GET_LOCAL(0)))),
2044 WASM_SET_LOCAL(
2045 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(4))))),
2046 WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO,
2047 WASM_GET_LOCAL(kSum)),
2048 WASM_GET_LOCAL(0)));
2049
2050 CHECK_EQ(0, r.Call(4 * (kSize - 1)));
2051 CHECK_NE(-99.25, buffer[0]);
2052 CHECK_EQ(71256.0f, buffer[0]);
2053 }
2054
2055
2056 #if WASM_64
2057 TEST(Run_Wasm_MemI64_Sum) {
2058 WasmRunner<uint64_t> r(MachineType::Int32());
2059 const int kNumElems = 20;
2060 const byte kSum = r.AllocateLocal(kAstI64);
2061 TestingModule module;
2062 uint64_t* memory = module.AddMemoryElems<uint64_t>(kNumElems);
2063 r.env()->module = &module;
2064
2065 BUILD(r, WASM_BLOCK(
2066 2, WASM_WHILE(
2067 WASM_GET_LOCAL(0),
2068 WASM_BLOCK(
2069 2, WASM_SET_LOCAL(
2070 kSum, WASM_I64_ADD(
2071 WASM_GET_LOCAL(kSum),
2072 WASM_LOAD_MEM(MachineType::Int64(),
2073 WASM_GET_LOCAL(0)))),
2074 WASM_SET_LOCAL(
2075 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(8))))),
2076 WASM_GET_LOCAL(1)));
2077
2078 // Run 4 trials.
2079 for (int i = 0; i < 3; i++) {
2080 module.RandomizeMemory(i * 33);
2081 uint64_t expected = 0;
2082 for (size_t j = kNumElems - 1; j > 0; j--) {
2083 expected += memory[j];
2084 }
2085 uint64_t result = r.Call(8 * (kNumElems - 1));
2086 CHECK_EQ(expected, result);
2087 }
2088 }
2089 #endif
2090
2091
2092 template <typename T>
2093 void GenerateAndRunFold(WasmOpcode binop, T* buffer, size_t size,
2094 LocalType astType, MachineType memType) {
2095 WasmRunner<int32_t> r(MachineType::Int32());
2096 const byte kAccum = r.AllocateLocal(astType);
2097 ModuleEnv module;
2098 module.mem_start = reinterpret_cast<uintptr_t>(buffer);
2099 module.mem_end = reinterpret_cast<uintptr_t>(buffer + size);
2100 r.env()->module = &module;
2101
2102 BUILD(
2103 r,
2104 WASM_BLOCK(
2105 4, WASM_SET_LOCAL(kAccum, WASM_LOAD_MEM(memType, WASM_ZERO)),
2106 WASM_WHILE(
2107 WASM_GET_LOCAL(0),
2108 WASM_BLOCK(
2109 2, WASM_SET_LOCAL(
2110 kAccum,
2111 WASM_BINOP(binop, WASM_GET_LOCAL(kAccum),
2112 WASM_LOAD_MEM(memType, WASM_GET_LOCAL(0)))),
2113 WASM_SET_LOCAL(
2114 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(sizeof(T)))))),
2115 WASM_STORE_MEM(memType, WASM_ZERO, WASM_GET_LOCAL(kAccum)),
2116 WASM_GET_LOCAL(0)));
2117 r.Call(static_cast<int>(sizeof(T) * (size - 1)));
2118 }
2119
2120
2121 TEST(Run_Wasm_MemF64_Mul) {
2122 const size_t kSize = 6;
2123 double buffer[kSize] = {1, 2, 2, 2, 2, 2};
2124 GenerateAndRunFold<double>(kExprF64Mul, buffer, kSize, kAstF64,
2125 MachineType::Float64());
2126 CHECK_EQ(32, buffer[0]);
2127 }
2128
2129
2130 TEST(Build_Wasm_Infinite_Loop) {
2131 WasmRunner<int32_t> r(MachineType::Int32());
2132 // Only build the graph and compile, don't run.
2133 BUILD(r, WASM_INFINITE_LOOP);
2134 }
2135
2136
2137 TEST(Build_Wasm_Infinite_Loop_effect) {
2138 WasmRunner<int32_t> r(MachineType::Int32());
2139 TestingModule module;
2140 module.AddMemoryElems<int8_t>(16);
2141 r.env()->module = &module;
2142
2143 // Only build the graph and compile, don't run.
2144 BUILD(r, WASM_LOOP(1, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)));
2145 }
2146
2147
2148 TEST(Run_Wasm_Unreachable0a) {
2149 WasmRunner<int32_t> r(MachineType::Int32());
2150 BUILD(r,
2151 WASM_BLOCK(2, WASM_BRV(0, WASM_I8(9)), WASM_RETURN(WASM_GET_LOCAL(0))));
2152 CHECK_EQ(9, r.Call(0));
2153 CHECK_EQ(9, r.Call(1));
2154 }
2155
2156
2157 TEST(Run_Wasm_Unreachable0b) {
2158 WasmRunner<int32_t> r(MachineType::Int32());
2159 BUILD(r, WASM_BLOCK(2, WASM_BRV(0, WASM_I8(7)), WASM_UNREACHABLE));
2160 CHECK_EQ(7, r.Call(0));
2161 CHECK_EQ(7, r.Call(1));
2162 }
2163
2164
2165 TEST(Build_Wasm_Unreachable1) {
2166 WasmRunner<int32_t> r(MachineType::Int32());
2167 BUILD(r, WASM_UNREACHABLE);
2168 }
2169
2170
2171 TEST(Build_Wasm_Unreachable2) {
2172 WasmRunner<int32_t> r(MachineType::Int32());
2173 BUILD(r, WASM_UNREACHABLE, WASM_UNREACHABLE);
2174 }
2175
2176
2177 TEST(Build_Wasm_Unreachable3) {
2178 WasmRunner<int32_t> r(MachineType::Int32());
2179 BUILD(r, WASM_UNREACHABLE, WASM_UNREACHABLE, WASM_UNREACHABLE);
2180 }
2181
2182
2183 TEST(Build_Wasm_UnreachableIf1) {
2184 WasmRunner<int32_t> r(MachineType::Int32());
2185 BUILD(r, WASM_UNREACHABLE, WASM_IF(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
2186 }
2187
2188
2189 TEST(Build_Wasm_UnreachableIf2) {
2190 WasmRunner<int32_t> r(MachineType::Int32());
2191 BUILD(r, WASM_UNREACHABLE,
2192 WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_UNREACHABLE));
2193 }
2194
2195
2196 TEST(Run_Wasm_Unreachable_Load) {
2197 WasmRunner<int32_t> r(MachineType::Int32());
2198 BUILD(r, WASM_BLOCK(2, WASM_BRV(0, WASM_GET_LOCAL(0)),
2199 WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0))));
2200 CHECK_EQ(11, r.Call(11));
2201 CHECK_EQ(21, r.Call(21));
2202 }
2203
2204
2205 TEST(Run_Wasm_Infinite_Loop_not_taken1) {
2206 WasmRunner<int32_t> r(MachineType::Int32());
2207 BUILD(r, WASM_BLOCK(2, WASM_IF(WASM_GET_LOCAL(0), WASM_INFINITE_LOOP),
2208 WASM_I8(45)));
2209 // Run the code, but don't go into the infinite loop.
2210 CHECK_EQ(45, r.Call(0));
2211 }
2212
2213
2214 TEST(Run_Wasm_Infinite_Loop_not_taken2) {
2215 WasmRunner<int32_t> r(MachineType::Int32());
2216 BUILD(r,
2217 WASM_BLOCK(1, WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(45)),
2218 WASM_INFINITE_LOOP)));
2219 // Run the code, but don't go into the infinite loop.
2220 CHECK_EQ(45, r.Call(1));
2221 }
2222
2223
2224 TEST(Run_Wasm_Infinite_Loop_not_taken2_brif) {
2225 WasmRunner<int32_t> r(MachineType::Int32());
2226 BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(45)),
2227 WASM_INFINITE_LOOP));
2228 // Run the code, but don't go into the infinite loop.
2229 CHECK_EQ(45, r.Call(1));
2230 }
2231
2232
2233 static void TestBuildGraphForUnop(WasmOpcode opcode, FunctionSig* sig) {
2234 WasmRunner<int32_t> r(MachineType::Int32());
2235 init_env(r.env(), sig);
2236 BUILD(r, static_cast<byte>(opcode), kExprGetLocal, 0);
2237 }
2238
2239
2240 static void TestBuildGraphForBinop(WasmOpcode opcode, FunctionSig* sig) {
2241 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
2242 init_env(r.env(), sig);
2243 BUILD(r, static_cast<byte>(opcode), kExprGetLocal, 0, kExprGetLocal, 1);
2244 }
2245
2246
2247 TEST(Build_Wasm_SimpleExprs) {
2248 // Test that the decoder can build a graph for all supported simple expressions.
2249 #define GRAPH_BUILD_TEST(name, opcode, sig) \
2250 if (WasmOpcodes::IsSupported(kExpr##name)) { \
2251 FunctionSig* sig = WasmOpcodes::Signature(kExpr##name); \
2252 printf("expression: " #name "\n"); \
2253 if (sig->parameter_count() == 1) { \
2254 TestBuildGraphForUnop(kExpr##name, sig); \
2255 } else { \
2256 TestBuildGraphForBinop(kExpr##name, sig); \
2257 } \
2258 }
2259
2260 FOREACH_SIMPLE_OPCODE(GRAPH_BUILD_TEST);
2261
2262 #undef GRAPH_BUILD_TEST
2263 }
2264
2265
2266 TEST(Run_Wasm_Int32LoadInt8_signext) {
2267 TestingModule module;
2268 const int kNumElems = 16;
2269 int8_t* memory = module.AddMemoryElems<int8_t>(kNumElems);
2270 module.RandomizeMemory();
2271 memory[0] = -1;
2272 WasmRunner<int32_t> r(MachineType::Int32());
2273 r.env()->module = &module;
2274 BUILD(r, WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0)));
2275
2276 for (size_t i = 0; i < kNumElems; i++) {
2277 CHECK_EQ(memory[i], r.Call(static_cast<int>(i)));
2278 }
2279 }
2280
2281
2282 TEST(Run_Wasm_Int32LoadInt8_zeroext) {
2283 TestingModule module;
2284 const int kNumElems = 16;
2285 byte* memory = module.AddMemory(kNumElems);
2286 module.RandomizeMemory(77);
2287 memory[0] = 255;
2288 WasmRunner<int32_t> r(MachineType::Int32());
2289 r.env()->module = &module;
2290 BUILD(r, WASM_LOAD_MEM(MachineType::Uint8(), WASM_GET_LOCAL(0)));
2291
2292 for (size_t i = 0; i < kNumElems; i++) {
2293 CHECK_EQ(memory[i], r.Call(static_cast<int>(i)));
2294 }
2295 }
2296
2297
2298 TEST(Run_Wasm_Int32LoadInt16_signext) {
2299 TestingModule module;
2300 const int kNumBytes = 16;
2301 byte* memory = module.AddMemory(kNumBytes);
2302 module.RandomizeMemory(888);
2303 memory[1] = 200;
2304 WasmRunner<int32_t> r(MachineType::Int32());
2305 r.env()->module = &module;
2306 BUILD(r, WASM_LOAD_MEM(MachineType::Int16(), WASM_GET_LOCAL(0)));
2307
2308 for (size_t i = 0; i < kNumBytes; i += 2) {
2309 int32_t expected = memory[i] | (static_cast<int8_t>(memory[i + 1]) << 8);
2310 CHECK_EQ(expected, r.Call(static_cast<int>(i)));
2311 }
2312 }
2313
2314
2315 TEST(Run_Wasm_Int32LoadInt16_zeroext) {
2316 TestingModule module;
2317 const int kNumBytes = 16;
2318 byte* memory = module.AddMemory(kNumBytes);
2319 module.RandomizeMemory(9999);
2320 memory[1] = 204;
2321 WasmRunner<int32_t> r(MachineType::Int32());
2322 r.env()->module = &module;
2323 BUILD(r, WASM_LOAD_MEM(MachineType::Uint16(), WASM_GET_LOCAL(0)));
2324
2325 for (size_t i = 0; i < kNumBytes; i += 2) {
2326 int32_t expected = memory[i] | (memory[i + 1] << 8);
2327 CHECK_EQ(expected, r.Call(static_cast<int>(i)));
2328 }
2329 }
2330
2331
2332 TEST(Run_WasmInt32Global) {
2333 TestingModule module;
2334 int32_t* global = module.AddGlobal<int32_t>(MachineType::Int32());
2335 WasmRunner<int32_t> r(MachineType::Int32());
2336 r.env()->module = &module;
2337 // global = global + p0
2338 BUILD(r, WASM_STORE_GLOBAL(
2339 0, WASM_I32_ADD(WASM_LOAD_GLOBAL(0), WASM_GET_LOCAL(0))));
2340
2341 *global = 116;
2342 for (int i = 9; i < 444444; i += 111111) {
2343 int32_t expected = *global + i;
2344 r.Call(i);
2345 CHECK_EQ(expected, *global);
2346 }
2347 }
2348
2349
2350 TEST(Run_WasmInt32Globals_DontAlias) {
2351 const int kNumGlobals = 3;
2352 TestingModule module;
2353 int32_t* globals[] = {module.AddGlobal<int32_t>(MachineType::Int32()),
2354 module.AddGlobal<int32_t>(MachineType::Int32()),
2355 module.AddGlobal<int32_t>(MachineType::Int32())};
2356
2357 for (int g = 0; g < kNumGlobals; g++) {
2358 // global = global + p0
2359 WasmRunner<int32_t> r(MachineType::Int32());
2360 r.env()->module = &module;
2361 BUILD(r, WASM_STORE_GLOBAL(
2362 g, WASM_I32_ADD(WASM_LOAD_GLOBAL(g), WASM_GET_LOCAL(0))));
2363
2364 // Check that reading/writing global number {g} doesn't alter the others.
2365 *globals[g] = 116 * g;
2366 int32_t before[kNumGlobals];
2367 for (int i = 9; i < 444444; i += 111113) {
2368 int32_t sum = *globals[g] + i;
2369 for (int j = 0; j < kNumGlobals; j++) before[j] = *globals[j];
2370 r.Call(i);
2371 for (int j = 0; j < kNumGlobals; j++) {
2372 int32_t expected = j == g ? sum : before[j];
2373 CHECK_EQ(expected, *globals[j]);
2374 }
2375 }
2376 }
2377 }
2378
2379
2380 #if WASM_64
2381 TEST(Run_WasmInt64Global) {
2382 TestingModule module;
2383 int64_t* global = module.AddGlobal<int64_t>(MachineType::Int64());
2384 WasmRunner<int32_t> r(MachineType::Int32());
2385 r.env()->module = &module;
2386 // global = global + p0
2387 BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL(
2388 0, WASM_I64_ADD(
2389 WASM_LOAD_GLOBAL(0),
2390 WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)))),
2391 WASM_ZERO));
2392
2393 *global = 0xFFFFFFFFFFFFFFFFLL;
2394 for (int i = 9; i < 444444; i += 111111) {
2395 int64_t expected = *global + i;
2396 r.Call(i);
2397 CHECK_EQ(expected, *global);
2398 }
2399 }
2400 #endif
2401
2402
2403 TEST(Run_WasmFloat32Global) {
2404 TestingModule module;
2405 float* global = module.AddGlobal<float>(MachineType::Float32());
2406 WasmRunner<int32_t> r(MachineType::Int32());
2407 r.env()->module = &module;
2408 // global = global + p0
2409 BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL(
2410 0, WASM_F32_ADD(
2411 WASM_LOAD_GLOBAL(0),
2412 WASM_F32_SCONVERT_I32(WASM_GET_LOCAL(0)))),
2413 WASM_ZERO));
2414
2415 *global = 1.25;
2416 for (int i = 9; i < 4444; i += 1111) {
2417 volatile float expected = *global + i;
2418 r.Call(i);
2419 CHECK_EQ(expected, *global);
2420 }
2421 }
2422
2423
2424 TEST(Run_WasmFloat64Global) {
2425 TestingModule module;
2426 double* global = module.AddGlobal<double>(MachineType::Float64());
2427 WasmRunner<int32_t> r(MachineType::Int32());
2428 r.env()->module = &module;
2429 // global = global + p0
2430 BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL(
2431 0, WASM_F64_ADD(
2432 WASM_LOAD_GLOBAL(0),
2433 WASM_F64_SCONVERT_I32(WASM_GET_LOCAL(0)))),
2434 WASM_ZERO));
2435
2436 *global = 1.25;
2437 for (int i = 9; i < 4444; i += 1111) {
2438 volatile double expected = *global + i;
2439 r.Call(i);
2440 CHECK_EQ(expected, *global);
2441 }
2442 }
2443
2444
2445 TEST(Run_WasmMixedGlobals) {
2446 TestingModule module;
2447 int32_t* unused = module.AddGlobal<int32_t>(MachineType::Int32());
2448 byte* memory = module.AddMemory(32);
2449
2450 int8_t* var_int8 = module.AddGlobal<int8_t>(MachineType::Int8());
2451 uint8_t* var_uint8 = module.AddGlobal<uint8_t>(MachineType::Uint8());
2452 int16_t* var_int16 = module.AddGlobal<int16_t>(MachineType::Int16());
2453 uint16_t* var_uint16 = module.AddGlobal<uint16_t>(MachineType::Uint16());
2454 int32_t* var_int32 = module.AddGlobal<int32_t>(MachineType::Int32());
2455 uint32_t* var_uint32 = module.AddGlobal<uint32_t>(MachineType::Uint32());
2456 float* var_float = module.AddGlobal<float>(MachineType::Float32());
2457 double* var_double = module.AddGlobal<double>(MachineType::Float64());
2458
2459 WasmRunner<int32_t> r(MachineType::Int32());
2460 r.env()->module = &module;
2461
2462 BUILD(
2463 r,
2464 WASM_BLOCK(
2465 9,
2466 WASM_STORE_GLOBAL(1, WASM_LOAD_MEM(MachineType::Int8(), WASM_ZERO)),
2467 WASM_STORE_GLOBAL(2, WASM_LOAD_MEM(MachineType::Uint8(), WASM_ZERO)),
2468 WASM_STORE_GLOBAL(3, WASM_LOAD_MEM(MachineType::Int16(), WASM_ZERO)),
2469 WASM_STORE_GLOBAL(4, WASM_LOAD_MEM(MachineType::Uint16(), WASM_ZERO)),
2470 WASM_STORE_GLOBAL(5, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)),
2471 WASM_STORE_GLOBAL(6, WASM_LOAD_MEM(MachineType::Uint32(), WASM_ZERO)),
2472 WASM_STORE_GLOBAL(7,
2473 WASM_LOAD_MEM(MachineType::Float32(), WASM_ZERO)),
2474 WASM_STORE_GLOBAL(8,
2475 WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO)),
2476 WASM_ZERO));
2477
2478 memory[0] = 0xaa;
2479 memory[1] = 0xcc;
2480 memory[2] = 0x55;
2481 memory[3] = 0xee;
2482 memory[4] = 0x33;
2483 memory[5] = 0x22;
2484 memory[6] = 0x11;
2485 memory[7] = 0x99;
2486 r.Call(1);
2487
2488 CHECK(static_cast<int8_t>(0xaa) == *var_int8);
2489 CHECK(static_cast<uint8_t>(0xaa) == *var_uint8);
2490 CHECK(static_cast<int16_t>(0xccaa) == *var_int16);
2491 CHECK(static_cast<uint16_t>(0xccaa) == *var_uint16);
2492 CHECK(static_cast<int32_t>(0xee55ccaa) == *var_int32);
2493 CHECK(static_cast<uint32_t>(0xee55ccaa) == *var_uint32);
2494 CHECK(bit_cast<float>(0xee55ccaa) == *var_float);
2495 CHECK(bit_cast<double>(0x99112233ee55ccaaULL) == *var_double);
2496
2497 USE(unused);
2498 }
2499
2500
2501 #if WASM_64
2502 // Test the WasmRunner with an Int64 return value and different numbers of
2503 // Int64 parameters.
2504 TEST(Run_TestI64WasmRunner) {
2505 {
2506 FOR_INT64_INPUTS(i) {
2507 WasmRunner<int64_t> r;
2508 BUILD(r, WASM_I64(*i));
2509 CHECK_EQ(*i, r.Call());
2510 }
2511 }
2512 {
2513 WasmRunner<int64_t> r(MachineType::Int64());
2514 BUILD(r, WASM_GET_LOCAL(0));
2515 FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
2516 }
2517 {
2518 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
2519 BUILD(r, WASM_I64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2520 FOR_INT64_INPUTS(i) {
2521 FOR_INT64_INPUTS(j) { CHECK_EQ(*i + *j, r.Call(*i, *j)); }
2522 }
2523 }
2524 {
2525 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64(),
2526 MachineType::Int64());
2527 BUILD(r, WASM_I64_ADD(WASM_GET_LOCAL(0),
2528 WASM_I64_ADD(WASM_GET_LOCAL(1), WASM_GET_LOCAL(2))));
2529 FOR_INT64_INPUTS(i) {
2530 FOR_INT64_INPUTS(j) {
2531 CHECK_EQ(*i + *j + *j, r.Call(*i, *j, *j));
2532 CHECK_EQ(*j + *i + *j, r.Call(*j, *i, *j));
2533 CHECK_EQ(*j + *j + *i, r.Call(*j, *j, *i));
2534 }
2535 }
2536 }
2537 {
2538 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64(),
2539 MachineType::Int64(), MachineType::Int64());
2540 BUILD(r, WASM_I64_ADD(WASM_GET_LOCAL(0),
2541 WASM_I64_ADD(WASM_GET_LOCAL(1),
2542 WASM_I64_ADD(WASM_GET_LOCAL(2),
2543 WASM_GET_LOCAL(3)))));
2544 FOR_INT64_INPUTS(i) {
2545 FOR_INT64_INPUTS(j) {
2546 CHECK_EQ(*i + *j + *j + *j, r.Call(*i, *j, *j, *j));
2547 CHECK_EQ(*j + *i + *j + *j, r.Call(*j, *i, *j, *j));
2548 CHECK_EQ(*j + *j + *i + *j, r.Call(*j, *j, *i, *j));
2549 CHECK_EQ(*j + *j + *j + *i, r.Call(*j, *j, *j, *i));
2550 }
2551 }
2552 }
2553 }
2554 #endif
2555
2556
2557 TEST(Run_WasmCallEmpty) {
2558 const int32_t kExpected = -414444;
2559 // Build the target function.
2560 TestSignatures sigs;
2561 TestingModule module;
2562 WasmFunctionCompiler t(sigs.i_v());
2563 BUILD(t, WASM_I32(kExpected));
2564 unsigned index = t.CompileAndAdd(&module);
2565
2566 // Build the calling function.
2567 WasmRunner<int32_t> r;
2568 r.env()->module = &module;
2569 BUILD(r, WASM_CALL_FUNCTION0(index));
2570
2571 int32_t result = r.Call();
2572 CHECK_EQ(kExpected, result);
2573 }
2574
2575
2576 TEST(Run_WasmCallVoid) {
2577 const byte kMemOffset = 8;
2578 const int32_t kElemNum = kMemOffset / sizeof(int32_t);
2579 const int32_t kExpected = -414444;
2580 // Build the target function.
2581 TestSignatures sigs;
2582 TestingModule module;
2583 module.AddMemory(16);
2584 module.RandomizeMemory();
2585 WasmFunctionCompiler t(sigs.v_v());
2586 t.env.module = &module;
2587 BUILD(t, WASM_STORE_MEM(MachineType::Int32(), WASM_I8(kMemOffset),
2588 WASM_I32(kExpected)));
2589 unsigned index = t.CompileAndAdd(&module);
2590
2591 // Build the calling function.
2592 WasmRunner<int32_t> r;
2593 r.env()->module = &module;
2594 BUILD(r, WASM_CALL_FUNCTION0(index),
2595 WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(kMemOffset)));
2596
2597 int32_t result = r.Call();
2598 CHECK_EQ(kExpected, result);
2599 CHECK_EQ(kExpected, module.raw_mem_start<int32_t>()[kElemNum]);
2600 }
2601
2602
2603 TEST(Run_WasmCall_Int32Add) {
2604 // Build the target function.
2605 TestSignatures sigs;
2606 TestingModule module;
2607 WasmFunctionCompiler t(sigs.i_ii());
2608 BUILD(t, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2609 unsigned index = t.CompileAndAdd(&module);
2610
2611 // Build the caller function.
2612 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
2613 r.env()->module = &module;
2614 BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2615
2616 FOR_INT32_INPUTS(i) {
2617 FOR_INT32_INPUTS(j) {
2618 int32_t expected = static_cast<int32_t>(static_cast<uint32_t>(*i) +
2619 static_cast<uint32_t>(*j));
2620 CHECK_EQ(expected, r.Call(*i, *j));
2621 }
2622 }
2623 }
2624
2625
2626 #if WASM_64
2627 TEST(Run_WasmCall_Int64Sub) {
2628 // Build the target function.
2629 TestSignatures sigs;
2630 TestingModule module;
2631 WasmFunctionCompiler t(sigs.l_ll());
2632 BUILD(t, WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2633 unsigned index = t.CompileAndAdd(&module);
2634
2635 // Build the caller function.
2636 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
2637 r.env()->module = &module;
2638 BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2639
2640 FOR_INT32_INPUTS(i) {
2641 FOR_INT32_INPUTS(j) {
2642 int64_t a = static_cast<int64_t>(*i) << 32 |
2643 (static_cast<int64_t>(*j) | 0xFFFFFFFF);
2644 int64_t b = static_cast<int64_t>(*j) << 32 |
2645 (static_cast<int64_t>(*i) | 0xFFFFFFFF);
2646
2647 int64_t expected = static_cast<int64_t>(static_cast<uint64_t>(a) -
2648 static_cast<uint64_t>(b));
2649 CHECK_EQ(expected, r.Call(a, b));
2650 }
2651 }
2652 }
2653 #endif
2654
2655
2656 TEST(Run_WasmCall_Float32Sub) {
2657 TestSignatures sigs;
2658 WasmFunctionCompiler t(sigs.f_ff());
2659
2660 // Build the target function.
2661 TestingModule module;
2662 BUILD(t, WASM_F32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2663 unsigned index = t.CompileAndAdd(&module);
2664
2665 // Builder the caller function.
2666 WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
2667 r.env()->module = &module;
2668 BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2669
2670 FOR_FLOAT32_INPUTS(i) {
2671 FOR_FLOAT32_INPUTS(j) { CheckFloatEq(*i - *j, r.Call(*i, *j)); }
2672 }
2673 }
2674
2675
2676 TEST(Run_WasmCall_Float64Sub) {
2677 WasmRunner<int32_t> r;
2678 TestingModule module;
2679 double* memory = module.AddMemoryElems<double>(16);
2680 r.env()->module = &module;
2681
2682 // TODO(titzer): convert to a binop test.
2683 BUILD(r, WASM_BLOCK(
2684 2, WASM_STORE_MEM(
2685 MachineType::Float64(), WASM_ZERO,
2686 WASM_F64_SUB(
2687 WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO),
2688 WASM_LOAD_MEM(MachineType::Float64(), WASM_I8(8)))),
2689 WASM_I8(107)));
2690
2691 FOR_FLOAT64_INPUTS(i) {
2692 FOR_FLOAT64_INPUTS(j) {
2693 memory[0] = *i;
2694 memory[1] = *j;
2695 double expected = *i - *j;
2696 CHECK_EQ(107, r.Call());
2697 if (expected != expected) {
2698 CHECK(memory[0] != memory[0]);
2699 } else {
2700 CHECK_EQ(expected, memory[0]);
2701 }
2702 }
2703 }
2704 }
2705
2706 #define ADD_CODE(vec, ...) \
2707 do { \
2708 byte __buf[] = {__VA_ARGS__}; \
2709 for (size_t i = 0; i < sizeof(__buf); i++) vec.push_back(__buf[i]); \
2710 } while (false)
2711
2712
2713 void Run_WasmMixedCall_N(int start) {
2714 const int kExpected = 6333;
2715 const int kElemSize = 8;
2716 TestSignatures sigs;
2717
2718 #if WASM_64
2719 static MachineType mixed[] = {
2720 MachineType::Int32(), MachineType::Float32(), MachineType::Int64(),
2721 MachineType::Float64(), MachineType::Float32(), MachineType::Int64(),
2722 MachineType::Int32(), MachineType::Float64(), MachineType::Float32(),
2723 MachineType::Float64(), MachineType::Int32(), MachineType::Int64(),
2724 MachineType::Int32(), MachineType::Int32()};
2725 #else
2726 static MachineType mixed[] = {
2727 MachineType::Int32(), MachineType::Float32(), MachineType::Float64(),
2728 MachineType::Float32(), MachineType::Int32(), MachineType::Float64(),
2729 MachineType::Float32(), MachineType::Float64(), MachineType::Int32(),
2730 MachineType::Int32(), MachineType::Int32()};
2731 #endif
2732
2733 int num_params = static_cast<int>(arraysize(mixed)) - start;
2734 for (int which = 0; which < num_params; which++) {
2735 Zone zone;
2736 TestingModule module;
2737 module.AddMemory(1024);
2738 MachineType* memtypes = &mixed[start];
2739 MachineType result = memtypes[which];
2740
2741 // =========================================================================
2742 // Build the selector function.
2743 // =========================================================================
2744 unsigned index;
2745 FunctionSig::Builder b(&zone, 1, num_params);
2746 b.AddReturn(WasmOpcodes::LocalTypeFor(result));
2747 for (int i = 0; i < num_params; i++) {
2748 b.AddParam(WasmOpcodes::LocalTypeFor(memtypes[i]));
2749 }
2750 WasmFunctionCompiler t(b.Build());
2751 t.env.module = &module;
2752 BUILD(t, WASM_GET_LOCAL(which));
2753 index = t.CompileAndAdd(&module);
2754
2755 // =========================================================================
2756 // Build the calling function.
2757 // =========================================================================
2758 WasmRunner<int32_t> r;
2759 r.env()->module = &module;
2760
2761 {
2762 std::vector<byte> code;
2763 ADD_CODE(code,
2764 static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(result, true)),
2765 WasmOpcodes::LoadStoreAccessOf(false));
2766 ADD_CODE(code, WASM_ZERO);
2767 ADD_CODE(code, kExprCallFunction, static_cast<byte>(index));
2768
2769 for (int i = 0; i < num_params; i++) {
2770 int offset = (i + 1) * kElemSize;
2771 ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I8(offset)));
2772 }
2773
2774 ADD_CODE(code, WASM_I32(kExpected));
2775 size_t end = code.size();
2776 code.push_back(0);
2777 r.Build(&code[0], &code[end]);
2778 }
2779
2780 // Run the code.
2781 for (int t = 0; t < 10; t++) {
2782 module.RandomizeMemory();
2783 CHECK_EQ(kExpected, r.Call());
2784
2785 int size = WasmOpcodes::MemSize(result);
2786 for (int i = 0; i < size; i++) {
2787 int base = (which + 1) * kElemSize;
2788 byte expected = module.raw_mem_at<byte>(base + i);
2789 byte result = module.raw_mem_at<byte>(i);
2790 CHECK_EQ(expected, result);
2791 }
2792 }
2793 }
2794 }
2795
2796
2797 TEST(Run_WasmMixedCall_0) { Run_WasmMixedCall_N(0); }
2798 TEST(Run_WasmMixedCall_1) { Run_WasmMixedCall_N(1); }
2799 TEST(Run_WasmMixedCall_2) { Run_WasmMixedCall_N(2); }
2800 TEST(Run_WasmMixedCall_3) { Run_WasmMixedCall_N(3); }
2801
2802
2803 TEST(Run_Wasm_CountDown_expr) {
2804 WasmRunner<int32_t> r(MachineType::Int32());
2805 BUILD(r, WASM_LOOP(
2806 3, WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)),
2807 WASM_BREAKV(0, WASM_GET_LOCAL(0))),
2808 WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(1))),
2809 WASM_CONTINUE(0)));
2810 CHECK_EQ(0, r.Call(1));
2811 CHECK_EQ(0, r.Call(10));
2812 CHECK_EQ(0, r.Call(100));
2813 }
2814
2815
2816 TEST(Run_Wasm_ExprBlock2a) {
2817 WasmRunner<int32_t> r(MachineType::Int32());
2818 BUILD(r, WASM_BLOCK(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))),
2819 WASM_I8(1)));
2820 CHECK_EQ(1, r.Call(0));
2821 CHECK_EQ(1, r.Call(1));
2822 }
2823
2824
2825 TEST(Run_Wasm_ExprBlock2b) {
2826 WasmRunner<int32_t> r(MachineType::Int32());
2827 BUILD(r, WASM_BLOCK(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))),
2828 WASM_I8(2)));
2829 CHECK_EQ(2, r.Call(0));
2830 CHECK_EQ(1, r.Call(1));
2831 }
2832
2833
2834 TEST(Run_Wasm_ExprBlock2c) {
2835 WasmRunner<int32_t> r(MachineType::Int32());
2836 BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(1)),
2837 WASM_I8(1)));
2838 CHECK_EQ(1, r.Call(0));
2839 CHECK_EQ(1, r.Call(1));
2840 }
2841
2842
2843 TEST(Run_Wasm_ExprBlock2d) {
2844 WasmRunner<int32_t> r(MachineType::Int32());
2845 BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(1)),
2846 WASM_I8(2)));
2847 CHECK_EQ(2, r.Call(0));
2848 CHECK_EQ(1, r.Call(1));
2849 }
2850
2851
2852 TEST(Run_Wasm_ExprBlock_ManualSwitch) {
2853 WasmRunner<int32_t> r(MachineType::Int32());
2854 BUILD(r, WASM_BLOCK(6, WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1)),
2855 WASM_BRV(0, WASM_I8(11))),
2856 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2)),
2857 WASM_BRV(0, WASM_I8(12))),
2858 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3)),
2859 WASM_BRV(0, WASM_I8(13))),
2860 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4)),
2861 WASM_BRV(0, WASM_I8(14))),
2862 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5)),
2863 WASM_BRV(0, WASM_I8(15))),
2864 WASM_I8(99)));
2865 CHECK_EQ(99, r.Call(0));
2866 CHECK_EQ(11, r.Call(1));
2867 CHECK_EQ(12, r.Call(2));
2868 CHECK_EQ(13, r.Call(3));
2869 CHECK_EQ(14, r.Call(4));
2870 CHECK_EQ(15, r.Call(5));
2871 CHECK_EQ(99, r.Call(6));
2872 }
2873
2874
2875 TEST(Run_Wasm_ExprBlock_ManualSwitch_brif) {
2876 WasmRunner<int32_t> r(MachineType::Int32());
2877 BUILD(r,
2878 WASM_BLOCK(6, WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1)),
2879 WASM_I8(11)),
2880 WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2)),
2881 WASM_I8(12)),
2882 WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3)),
2883 WASM_I8(13)),
2884 WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4)),
2885 WASM_I8(14)),
2886 WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5)),
2887 WASM_I8(15)),
2888 WASM_I8(99)));
2889 CHECK_EQ(99, r.Call(0));
2890 CHECK_EQ(11, r.Call(1));
2891 CHECK_EQ(12, r.Call(2));
2892 CHECK_EQ(13, r.Call(3));
2893 CHECK_EQ(14, r.Call(4));
2894 CHECK_EQ(15, r.Call(5));
2895 CHECK_EQ(99, r.Call(6));
2896 }
2897
2898
2899 TEST(Run_Wasm_nested_ifs) {
2900 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
2901
2902 BUILD(r, WASM_IF_ELSE(
2903 WASM_GET_LOCAL(0),
2904 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(11), WASM_I8(12)),
2905 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(13), WASM_I8(14))));
2906
2907
2908 CHECK_EQ(11, r.Call(1, 1));
2909 CHECK_EQ(12, r.Call(1, 0));
2910 CHECK_EQ(13, r.Call(0, 1));
2911 CHECK_EQ(14, r.Call(0, 0));
2912 }
2913
2914
2915 TEST(Run_Wasm_ExprBlock_if) {
2916 WasmRunner<int32_t> r(MachineType::Int32());
2917
2918 BUILD(r,
2919 WASM_BLOCK(1, WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(11)),
2920 WASM_BRV(0, WASM_I8(14)))));
2921
2922 CHECK_EQ(11, r.Call(1));
2923 CHECK_EQ(14, r.Call(0));
2924 }
2925
2926
2927 TEST(Run_Wasm_ExprBlock_nested_ifs) {
2928 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
2929
2930 BUILD(r, WASM_BLOCK(
2931 1, WASM_IF_ELSE(
2932 WASM_GET_LOCAL(0),
2933 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I8(11)),
2934 WASM_BRV(0, WASM_I8(12))),
2935 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I8(13)),
2936 WASM_BRV(0, WASM_I8(14))))));
2937
2938
2939 CHECK_EQ(11, r.Call(1, 1));
2940 CHECK_EQ(12, r.Call(1, 0));
2941 CHECK_EQ(13, r.Call(0, 1));
2942 CHECK_EQ(14, r.Call(0, 0));
2943 }
2944
2945
2946 TEST(Run_Wasm_ExprLoop_nested_ifs) {
2947 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
2948
2949 BUILD(r, WASM_LOOP(
2950 1, WASM_IF_ELSE(
2951 WASM_GET_LOCAL(0),
2952 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(1, WASM_I8(11)),
2953 WASM_BRV(1, WASM_I8(12))),
2954 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(1, WASM_I8(13)),
2955 WASM_BRV(1, WASM_I8(14))))));
2956
2957
2958 CHECK_EQ(11, r.Call(1, 1));
2959 CHECK_EQ(12, r.Call(1, 0));
2960 CHECK_EQ(13, r.Call(0, 1));
2961 CHECK_EQ(14, r.Call(0, 0));
2962 }
2963
2964
2965 #if WASM_64
2966 TEST(Run_Wasm_LoadStoreI64_sx) {
2967 byte loads[] = {kExprI64LoadMem8S, kExprI64LoadMem16S, kExprI64LoadMem32S,
2968 kExprI64LoadMem};
2969
2970 for (size_t m = 0; m < arraysize(loads); m++) {
2971 WasmRunner<int64_t> r;
2972 TestingModule module;
2973 byte* memory = module.AddMemoryElems<byte>(16);
2974 r.env()->module = &module;
2975
2976 byte code[] = {kExprI64StoreMem, 0, kExprI8Const, 8,
2977 loads[m], 0, kExprI8Const, 0};
2978
2979 r.Build(code, code + arraysize(code));
2980
2981 // Try a bunch of different negative values.
2982 for (int i = -1; i >= -128; i -= 11) {
2983 int size = 1 << m;
2984 module.ZeroMemory();
2985 memory[size - 1] = static_cast<byte>(i); // set the high order byte.
2986
2987 int64_t expected = static_cast<int64_t>(i) << ((size - 1) * 8);
2988
2989 CHECK_EQ(expected, r.Call());
2990 CHECK_EQ(static_cast<byte>(i), memory[8 + size - 1]);
2991 for (int j = size; j < 8; j++) {
2992 CHECK_EQ(255, memory[8 + j]);
2993 }
2994 }
2995 }
2996 }
2997
2998
2999 #endif
3000
3001
3002 TEST(Run_Wasm_SimpleCallIndirect) {
3003 Isolate* isolate = CcTest::InitIsolateOnce();
3004
3005 WasmRunner<int32_t> r(MachineType::Int32());
3006 TestSignatures sigs;
3007 TestingModule module;
3008 r.env()->module = &module;
3009 WasmFunctionCompiler t1(sigs.i_ii());
3010 BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
3011 t1.CompileAndAdd(&module);
3012
3013 WasmFunctionCompiler t2(sigs.i_ii());
3014 BUILD(t2, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
3015 t2.CompileAndAdd(&module);
3016
3017 // Signature table.
3018 module.AddSignature(sigs.f_ff());
3019 module.AddSignature(sigs.i_ii());
3020 module.AddSignature(sigs.d_dd());
3021
3022 // Function table.
3023 int table_size = 2;
3024 std::vector<uint16_t> function_table;
3025 module.module->function_table = &function_table;
3026 module.module->function_table->push_back(0);
3027 module.module->function_table->push_back(1);
3028
3029 // Function table.
3030 Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size);
3031 fixed->set(0, Smi::FromInt(1));
3032 fixed->set(1, Smi::FromInt(1));
3033 fixed->set(2, *module.function_code->at(0));
3034 fixed->set(3, *module.function_code->at(1));
3035 module.function_table = fixed;
3036
3037 // Builder the caller function.
3038 BUILD(r, WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22)));
3039
3040 CHECK_EQ(88, r.Call(0));
3041 CHECK_EQ(44, r.Call(1));
3042 CHECK_TRAP(r.Call(2));
3043 }
3044
3045
3046 TEST(Run_Wasm_MultipleCallIndirect) {
3047 Isolate* isolate = CcTest::InitIsolateOnce();
3048
3049 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32(),
3050 MachineType::Int32());
3051 TestSignatures sigs;
3052 TestingModule module;
3053 r.env()->module = &module;
3054 WasmFunctionCompiler t1(sigs.i_ii());
3055 BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
3056 t1.CompileAndAdd(&module);
3057
3058 WasmFunctionCompiler t2(sigs.i_ii());
3059 BUILD(t2, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
3060 t2.CompileAndAdd(&module);
3061
3062 // Signature table.
3063 module.AddSignature(sigs.f_ff());
3064 module.AddSignature(sigs.i_ii());
3065 module.AddSignature(sigs.d_dd());
3066
3067 // Function table.
3068 int table_size = 2;
3069 std::vector<uint16_t> function_table;
3070 module.module->function_table = &function_table;
3071 module.module->function_table->push_back(0);
3072 module.module->function_table->push_back(1);
3073
3074 // Function table.
3075 Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size);
3076 fixed->set(0, Smi::FromInt(1));
3077 fixed->set(1, Smi::FromInt(1));
3078 fixed->set(2, *module.function_code->at(0));
3079 fixed->set(3, *module.function_code->at(1));
3080 module.function_table = fixed;
3081
3082 // Builder the caller function.
3083 BUILD(r,
3084 WASM_I32_ADD(WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1),
3085 WASM_GET_LOCAL(2)),
3086 WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(1), WASM_GET_LOCAL(2),
3087 WASM_GET_LOCAL(0))));
3088
3089 CHECK_EQ(5, r.Call(0, 1, 2));
3090 CHECK_EQ(19, r.Call(0, 1, 9));
3091 CHECK_EQ(1, r.Call(1, 0, 2));
3092 CHECK_EQ(1, r.Call(1, 0, 9));
3093
3094 CHECK_TRAP(r.Call(0, 2, 1));
3095 CHECK_TRAP(r.Call(1, 2, 0));
3096 CHECK_TRAP(r.Call(2, 0, 1));
3097 CHECK_TRAP(r.Call(2, 1, 0));
3098 }
3099
3100
3101 TEST(Run_Wasm_F32Floor) {
3102 WasmRunner<float> r(MachineType::Float32());
3103 BUILD(r, WASM_F32_FLOOR(WASM_GET_LOCAL(0)));
3104
3105 FOR_FLOAT32_INPUTS(i) { CheckFloatEq(floor(*i), r.Call(*i)); }
3106 }
3107
3108
3109 TEST(Run_Wasm_F32Ceil) {
3110 WasmRunner<float> r(MachineType::Float32());
3111 BUILD(r, WASM_F32_CEIL(WASM_GET_LOCAL(0)));
3112
3113 FOR_FLOAT32_INPUTS(i) { CheckFloatEq(ceil(*i), r.Call(*i)); }
3114 }
3115
3116
3117 TEST(Run_Wasm_F32Trunc) {
3118 WasmRunner<float> r(MachineType::Float32());
3119 BUILD(r, WASM_F32_TRUNC(WASM_GET_LOCAL(0)));
3120
3121 FOR_FLOAT32_INPUTS(i) { CheckFloatEq(trunc(*i), r.Call(*i)); }
3122 }
3123
3124
3125 TEST(Run_Wasm_F32NearestInt) {
3126 WasmRunner<float> r(MachineType::Float32());
3127 BUILD(r, WASM_F32_NEARESTINT(WASM_GET_LOCAL(0)));
3128
3129 FOR_FLOAT32_INPUTS(i) { CheckFloatEq(nearbyint(*i), r.Call(*i)); }
3130 }
3131
3132
3133 TEST(Run_Wasm_F64Floor) {
3134 WasmRunner<double> r(MachineType::Float64());
3135 BUILD(r, WASM_F64_FLOOR(WASM_GET_LOCAL(0)));
3136
3137 FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(floor(*i), r.Call(*i)); }
3138 }
3139
3140
3141 TEST(Run_Wasm_F64Ceil) {
3142 WasmRunner<double> r(MachineType::Float64());
3143 BUILD(r, WASM_F64_CEIL(WASM_GET_LOCAL(0)));
3144
3145 FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(ceil(*i), r.Call(*i)); }
3146 }
3147
3148
3149 TEST(Run_Wasm_F64Trunc) {
3150 WasmRunner<double> r(MachineType::Float64());
3151 BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0)));
3152
3153 FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(trunc(*i), r.Call(*i)); }
3154 }
3155
3156
3157 TEST(Run_Wasm_F64NearestInt) {
3158 WasmRunner<double> r(MachineType::Float64());
3159 BUILD(r, WASM_F64_NEARESTINT(WASM_GET_LOCAL(0)));
3160
3161 FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(nearbyint(*i), r.Call(*i)); }
3162 }
3163
3164
3165 TEST(Run_Wasm_F32Min) {
3166 WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
3167 BUILD(r, WASM_F32_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
3168
3169 FOR_FLOAT32_INPUTS(i) {
3170 FOR_FLOAT32_INPUTS(j) {
3171 float expected = *i < *j ? *i : *j;
3172 CheckFloatEq(expected, r.Call(*i, *j));
3173 }
3174 }
3175 }
3176
3177
3178 TEST(Run_Wasm_F64Min) {
3179 WasmRunner<double> r(MachineType::Float64(), MachineType::Float64());
3180 BUILD(r, WASM_F64_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
3181
3182 FOR_FLOAT64_INPUTS(i) {
3183 FOR_FLOAT64_INPUTS(j) {
3184 double expected = *i < *j ? *i : *j;
3185 CheckDoubleEq(expected, r.Call(*i, *j));
3186 }
3187 }
3188 }
3189
3190
3191 TEST(Run_Wasm_F32Max) {
3192 WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
3193 BUILD(r, WASM_F32_MAX(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
3194
3195 FOR_FLOAT32_INPUTS(i) {
3196 FOR_FLOAT32_INPUTS(j) {
3197 float expected = *i > *j ? *i : *j;
3198 CheckFloatEq(expected, r.Call(*i, *j));
3199 }
3200 }
3201 }
3202
3203
3204 TEST(Run_Wasm_F64Max) {
3205 WasmRunner<double> r(MachineType::Float64(), MachineType::Float64());
3206 BUILD(r, WASM_F64_MAX(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
3207
3208 FOR_FLOAT64_INPUTS(i) {
3209 FOR_FLOAT64_INPUTS(j) {
3210 double expected = *i > *j ? *i : *j;
3211 CheckDoubleEq(expected, r.Call(*i, *j));
3212 }
3213 }
3214 }
3215
3216
3217 #if WASM_64
3218 TEST(Run_Wasm_F32SConvertI64) {
3219 WasmRunner<float> r(MachineType::Int64());
3220 BUILD(r, WASM_F32_SCONVERT_I64(WASM_GET_LOCAL(0)));
3221 FOR_INT64_INPUTS(i) { CHECK_EQ(static_cast<float>(*i), r.Call(*i)); }
3222 }
3223
3224
3225 TEST(Run_Wasm_F32UConvertI64) {
3226 WasmRunner<float> r(MachineType::Uint64());
3227 BUILD(r, WASM_F32_UCONVERT_I64(WASM_GET_LOCAL(0)));
3228 FOR_UINT64_INPUTS(i) { CHECK_EQ(static_cast<float>(*i), r.Call(*i)); }
3229 }
3230
3231
3232 TEST(Run_Wasm_F64SConvertI64) {
3233 WasmRunner<double> r(MachineType::Int64());
3234 BUILD(r, WASM_F64_SCONVERT_I64(WASM_GET_LOCAL(0)));
3235 FOR_INT64_INPUTS(i) { CHECK_EQ(static_cast<double>(*i), r.Call(*i)); }
3236 }
3237
3238
3239 TEST(Run_Wasm_F64UConvertI64) {
3240 WasmRunner<double> r(MachineType::Uint64());
3241 BUILD(r, WASM_F64_UCONVERT_I64(WASM_GET_LOCAL(0)));
3242 FOR_UINT64_INPUTS(i) { CHECK_EQ(static_cast<double>(*i), r.Call(*i)); }
3243 }
3244
3245
3246 #endif
3247
3248
3249 TEST(Run_Wasm_F64CopySign) {
3250 WasmRunner<double> r(MachineType::Float64(), MachineType::Float64());
3251 BUILD(r, WASM_F64_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
3252
3253 FOR_FLOAT64_INPUTS(i) {
3254 FOR_FLOAT64_INPUTS(j) { CheckDoubleEq(copysign(*i, *j), r.Call(*i, *j)); }
3255 }
3256 }
3257
3258
3259 TEST(Run_Wasm_F32CopySign) {
3260 WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
3261 BUILD(r, WASM_F32_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
3262
3263 FOR_FLOAT32_INPUTS(i) {
3264 FOR_FLOAT32_INPUTS(j) { CheckFloatEq(copysign(*i, *j), r.Call(*i, *j)); }
3265 }
3266 }
OLDNEW
« no previous file with comments | « test/cctest/cctest.gyp ('k') | test/cctest/wasm/test-run-wasm-module.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698