Update WASM towards 0xc
[WebKit-https.git] / Source / JavaScriptCore / testWASM.cpp
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include "B3Compilation.h"
29 #include "InitializeThreading.h"
30 #include "JSCJSValueInlines.h"
31 #include "JSString.h"
32 #include "LLIntThunks.h"
33 #include "ProtoCallFrame.h"
34 #include "VM.h"
35 #include "WASMPlan.h"
36 #include <wtf/DataLog.h>
37 #include <wtf/LEBDecoder.h>
38
39 class CommandLine {
40 public:
41     CommandLine(int argc, char** argv)
42     {
43         parseArguments(argc, argv);
44     }
45
46     Vector<String> m_arguments;
47     bool m_runLEBTests { false };
48     bool m_runWASMTests { false };
49
50     void parseArguments(int, char**);
51 };
52
53 static NO_RETURN void printUsageStatement(bool help = false)
54 {
55     fprintf(stderr, "Usage: testWASM [options]\n");
56     fprintf(stderr, "  -h|--help  Prints this help message\n");
57     fprintf(stderr, "  -l|--leb   Runs the LEB decoder tests\n");
58     fprintf(stderr, "  -w|--web   Run the WASM tests\n");
59     fprintf(stderr, "\n");
60
61     exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
62 }
63
64 void CommandLine::parseArguments(int argc, char** argv)
65 {
66     int i = 1;
67
68     for (; i < argc; ++i) {
69         const char* arg = argv[i];
70         if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
71             printUsageStatement(true);
72
73         if (!strcmp(arg, "-l") || !strcmp(arg, "--leb"))
74             m_runLEBTests = true;
75
76         if (!strcmp(arg, "-w") || !strcmp(arg, "--web"))
77             m_runWASMTests = true;
78     }
79
80     for (; i < argc; ++i)
81         m_arguments.append(argv[i]);
82
83 }
84
85 StaticLock crashLock;
86
87 #define CHECK_EQ(x, y) do { \
88         auto __x = (x); \
89         auto __y = (y); \
90         if (__x == __y) \
91         break; \
92         crashLock.lock(); \
93         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, toCString(#x " == " #y, " (" #x " == ", __x, ", " #y " == ", __y, ")").data()); \
94         CRASH(); \
95     } while (false)
96
97 #define FOR_EACH_UNSIGNED_LEB_TEST(macro) \
98     /* Simple tests that use all the bits in the array */ \
99     macro(({ 0x07 }), 0, true, 0x7lu, 1lu) \
100     macro(({ 0x77 }), 0, true, 0x77lu, 1lu) \
101     macro(({ 0x80, 0x07 }), 0, true, 0x380lu, 2lu) \
102     macro(({ 0x89, 0x12 }), 0, true, 0x909lu, 2lu) \
103     macro(({ 0xf3, 0x85, 0x02 }), 0, true, 0x82f3lu, 3lu) \
104     macro(({ 0xf3, 0x85, 0xff, 0x74 }), 0, true, 0xe9fc2f3lu, 4lu) \
105     macro(({ 0xf3, 0x85, 0xff, 0xf4, 0x7f }), 0, true, 0xfe9fc2f3lu, 5lu) \
106     /* Test with extra trailing numbers */ \
107     macro(({ 0x07, 0x80 }), 0, true, 0x7lu, 1lu) \
108     macro(({ 0x07, 0x75 }), 0, true, 0x7lu, 1lu) \
109     macro(({ 0xf3, 0x85, 0xff, 0x74, 0x43 }), 0, true, 0xe9fc2f3lu, 4lu) \
110     macro(({ 0xf3, 0x85, 0xff, 0x74, 0x80 }), 0, true, 0xe9fc2f3lu, 4lu) \
111     /* Test with preceeding numbers */ \
112     macro(({ 0xf3, 0x07 }), 1, true, 0x7lu, 2lu) \
113     macro(({ 0x03, 0x07 }), 1, true, 0x7lu, 2lu) \
114     macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77 }), 5, true, 0x77lu, 6lu) \
115     macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77 }), 5, true, 0x77lu, 6ul) \
116     macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02 }), 3, true, 0x82f3lu, 6lu) \
117     /* Test in the middle */ \
118     macro(({ 0xf3, 0x07, 0x89 }), 1, true, 0x7lu, 2lu) \
119     macro(({ 0x03, 0x07, 0x23 }), 1, true, 0x7lu, 2lu) \
120     macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77, 0x43 }), 5, true, 0x77lu, 6lu) \
121     macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77, 0xf9 }), 5, true, 0x77lu, 6lu) \
122     macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02, 0xa4 }), 3, true, 0x82f3lu, 6lu) \
123     /* Test decode too long */ \
124     macro(({ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}), 0, false, 0x0lu, 0lu) \
125     macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 1, false, 0x0lu, 0lu) \
126     macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 0, false, 0x0lu, 0lu) \
127     /* Test decode off end of array */ \
128     macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 2, false, 0x0lu, 0lu) \
129
130
131 #define TEST_UNSIGNED_LEB_DECODE(init, startOffset, expectedStatus, expectedResult, expectedOffset) \
132     { \
133         Vector<uint8_t> vector = Vector<uint8_t> init; \
134         size_t offset = startOffset; \
135         uint32_t result; \
136         bool status = decodeUInt32(vector.data(), vector.size(), offset, result); \
137         CHECK_EQ(status, expectedStatus); \
138         if (expectedStatus) { \
139             CHECK_EQ(result, expectedResult); \
140             CHECK_EQ(offset, expectedOffset); \
141         } \
142     };
143
144
145 #define FOR_EACH_SIGNED_LEB_TEST(macro) \
146     /* Simple tests that use all the bits in the array */ \
147     macro(({ 0x07 }), 0, true, 0x7, 1lu) \
148     macro(({ 0x77 }), 0, true, -0x9, 1lu) \
149     macro(({ 0x80, 0x07 }), 0, true, 0x380, 2lu) \
150     macro(({ 0x89, 0x12 }), 0, true, 0x909, 2lu) \
151     macro(({ 0xf3, 0x85, 0x02 }), 0, true, 0x82f3, 3lu) \
152     macro(({ 0xf3, 0x85, 0xff, 0x74 }), 0, true, 0xfe9fc2f3, 4lu) \
153     macro(({ 0xf3, 0x85, 0xff, 0xf4, 0x7f }), 0, true, 0xfe9fc2f3, 5lu) \
154     /* Test with extra trailing numbers */ \
155     macro(({ 0x07, 0x80 }), 0, true, 0x7, 1lu) \
156     macro(({ 0x07, 0x75 }), 0, true, 0x7, 1lu) \
157     macro(({ 0xf3, 0x85, 0xff, 0x74, 0x43 }), 0, true, 0xfe9fc2f3, 4lu) \
158     macro(({ 0xf3, 0x85, 0xff, 0x74, 0x80 }), 0, true, 0xfe9fc2f3, 4lu) \
159     /* Test with preceeding numbers */ \
160     macro(({ 0xf3, 0x07 }), 1, true, 0x7, 2lu) \
161     macro(({ 0x03, 0x07 }), 1, true, 0x7, 2lu) \
162     macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77 }), 5, true, -0x9, 6lu) \
163     macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77 }), 5, true, -0x9, 6lu) \
164     macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02 }), 3, true, 0x82f3, 6lu) \
165     /* Test in the middle */ \
166     macro(({ 0xf3, 0x07, 0x89 }), 1, true, 0x7, 2lu) \
167     macro(({ 0x03, 0x07, 0x23 }), 1, true, 0x7, 2lu) \
168     macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77, 0x43 }), 5, true, -0x9, 6lu) \
169     macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77, 0xf9 }), 5, true, -0x9, 6lu) \
170     macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02, 0xa4 }), 3, true, 0x82f3, 6lu) \
171     /* Test decode too long */ \
172     macro(({ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}), 0, false, 0x0, 0lu) \
173     macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 1, false, 0x0, 0lu) \
174     macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 0, false, 0x0, 0lu) \
175     /* Test decode off end of array */ \
176     macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 2, false, 0x0, 0lu) \
177
178
179 #define TEST_SIGNED_LEB_DECODE(init, startOffset, expectedStatus, expectedResult, expectedOffset) \
180     { \
181         Vector<uint8_t> vector = Vector<uint8_t> init; \
182         size_t offset = startOffset; \
183         int32_t result; \
184         bool status = decodeInt32(vector.data(), vector.size(), offset, result); \
185         CHECK_EQ(status, expectedStatus); \
186         if (expectedStatus) { \
187             int32_t expected = expectedResult; \
188             CHECK_EQ(result, expected); \
189             CHECK_EQ(offset, expectedOffset); \
190         } \
191     };
192
193
194 static void runLEBTests()
195 {
196     FOR_EACH_UNSIGNED_LEB_TEST(TEST_UNSIGNED_LEB_DECODE)
197     FOR_EACH_SIGNED_LEB_TEST(TEST_SIGNED_LEB_DECODE)
198 }
199
200 #if ENABLE(WEBASSEMBLY)
201
202 static JSC::VM* vm;
203
204 using namespace JSC;
205 using namespace WASM;
206 using namespace B3;
207
208 template<typename T>
209 T invoke(MacroAssemblerCodePtr ptr, std::initializer_list<JSValue> args)
210 {
211     JSValue firstArgument;
212     // Since vmEntryToJavaScript expects a this value we claim there is one... there isn't.
213     int argCount = 1;
214     JSValue* remainingArguments = nullptr;
215     if (args.size()) {
216         remainingArguments = const_cast<JSValue*>(args.begin());
217         firstArgument = *remainingArguments;
218         remainingArguments++;
219         argCount = args.size();
220     }
221
222     ProtoCallFrame protoCallFrame;
223     protoCallFrame.init(nullptr, nullptr, firstArgument, argCount, remainingArguments);
224
225     // This won't work for floating point values but we don't have those yet.
226     return static_cast<T>(vmEntryToWASM(ptr.executableAddress(), vm, &protoCallFrame));
227 }
228
229 template<typename T>
230 T invoke(const Compilation& code, std::initializer_list<JSValue> args)
231 {
232     return invoke<T>(code.code(), args);
233 }
234
235 inline JSValue box(uint64_t value)
236 {
237     return JSValue::decode(value);
238 }
239
240 // For now we inline the test files.
241 static void runWASMTests()
242 {
243     {
244         // Generated from:
245         //    (module
246         //     (func (export "dumb-eq") (param $x i32) (param $y i32) (result i32)
247         //      (if (i32.eq (get_local $x) (get_local $y))
248         //       (then (br 0))
249         //       (else (return (i32.const 1))))
250         //      (return (i32.const 0))
251         //      )
252         //     )
253         Vector<uint8_t> vector = {
254             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
255             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8b, 0x80,
256             0x80, 0x80, 0x00, 0x01, 0x07, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x65, 0x71, 0x00, 0x00, 0x0a, 0x99,
257             0x80, 0x80, 0x80, 0x00, 0x01, 0x93, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x4d,
258             0x03, 0x00, 0x06, 0x00, 0x04, 0x10, 0x01, 0x09, 0x0f, 0x10, 0x00, 0x09, 0x0f
259         };
260
261         Plan plan(*vm, vector);
262         if (plan.result.size() != 1 || !plan.result[0]) {
263             dataLogLn("Module failed to compile correctly.");
264             CRASH();
265         }
266
267         // Test this doesn't crash.
268         CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 1);
269         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(0) }), 1);
270         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(1) }), 1);
271         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(2) }), 1);
272         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(2) }), 0);
273         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(1) }), 0);
274         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(6) }), 1);
275         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(6) }), 1);
276     }
277
278     {
279         // Generated from:
280         //    (module
281         //     (func (export "dumb-less-than") (param $x i32) (param $y i32) (result i32)
282         //      (loop
283         //       (if (i32.eq (get_local $x) (get_local $y))
284         //        (then (return (i32.const 0)))
285         //        (else (if (i32.eq (get_local $x) (i32.const 0))
286         //               (return (i32.const 1)))))
287         //       (set_local $x (i32.sub (get_local $x) (i32.const 1)))
288         //       (br 0)
289         //       )
290         //      )
291         //     )
292         Vector<uint8_t> vector = {
293             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
294             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x92, 0x80,
295             0x80, 0x80, 0x00, 0x01, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
296             0x68, 0x61, 0x6e, 0x00, 0x00, 0x0a, 0xac, 0x80, 0x80, 0x80, 0x00, 0x01, 0xa6, 0x80, 0x80, 0x80,
297             0x00, 0x00, 0x02, 0x00, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x03, 0x00, 0x10, 0x00, 0x09, 0x04, 0x14,
298             0x00, 0x10, 0x00, 0x4d, 0x03, 0x00, 0x10, 0x01, 0x09, 0x0f, 0x0f, 0x14, 0x00, 0x10, 0x01, 0x41,
299             0x15, 0x00, 0x06, 0x00, 0x0f, 0x00, 0x0f
300         };
301
302         Plan plan(*vm, vector);
303         if (plan.result.size() != 1 || !plan.result[0]) {
304             dataLogLn("Module failed to compile correctly.");
305             CRASH();
306         }
307
308         // Test this doesn't crash.
309         CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 1);
310         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(0) }), 0);
311         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(1) }), 0);
312         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(2) }), 1);
313         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(2) }), 0);
314         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(1) }), 0);
315         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(6) }), 1);
316         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(6) }), 0);
317     }
318
319
320     {
321         // Generated from: (module (func (export "return-i32") (result i32) (return (i32.const 5))) )
322         Vector<uint8_t> vector = {
323             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
324             0x00, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8e, 0x80, 0x80, 0x80,
325             0x00, 0x01, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x00, 0x00, 0x0a,
326             0x8b, 0x80, 0x80, 0x80, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x09, 0x0f
327         };
328
329         Plan plan(*vm, vector);
330         if (plan.result.size() != 1 || !plan.result[0]) {
331             dataLogLn("Module failed to compile correctly.");
332             CRASH();
333         }
334
335         // Test this doesn't crash.
336         CHECK_EQ(invoke<int>(*plan.result[0], { }), 5);
337     }
338
339
340     {
341         // Generated from: (module (func (export "return-i32") (result i32) (return (i32.add (i32.const 5) (i32.const 6)))) )
342         Vector<uint8_t> vector = {
343             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
344             0x00, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8e, 0x80, 0x80, 0x80,
345             0x00, 0x01, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x00, 0x00, 0x0a,
346             0x8e, 0x80, 0x80, 0x80, 0x00, 0x01, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x10, 0x06,
347             0x40, 0x09, 0x0f
348         };
349
350         Plan plan(*vm, vector);
351         if (plan.result.size() != 1 || !plan.result[0]) {
352             dataLogLn("Module failed to compile correctly.");
353             CRASH();
354         }
355
356         // Test this doesn't crash.
357         CHECK_EQ(invoke<int>(*plan.result[0], { }), 11);
358     }
359
360     {
361         // Generated from: (module (func (export "return-i32") (result i32) (return (i32.add (i32.add (i32.const 5) (i32.const 3)) (i32.const 3)))) )
362         Vector<uint8_t> vector = {
363             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
364             0x00, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8e, 0x80, 0x80, 0x80,
365             0x00, 0x01, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x00, 0x00, 0x0a,
366             0x91, 0x80, 0x80, 0x80, 0x00, 0x01, 0x8b, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x10, 0x03,
367             0x40, 0x10, 0x03, 0x40, 0x09, 0x0f
368         };
369
370         Plan plan(*vm, vector);
371         if (plan.result.size() != 1 || !plan.result[0]) {
372             dataLogLn("Module failed to compile correctly.");
373             CRASH();
374         }
375
376         // Test this doesn't crash.
377         CHECK_EQ(invoke<int>(*plan.result[0], { }), 11);
378     }
379
380     {
381         // Generated from: (module (func (export "return-i32") (result i32) (block (return (i32.add (i32.add (i32.const 5) (i32.const 3)) (i32.const 3)))) (unreachable)) )
382         Vector<uint8_t> vector = {
383             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
384             0x00, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8e, 0x80, 0x80, 0x80,
385             0x00, 0x01, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x00, 0x00, 0x0a,
386             0x95, 0x80, 0x80, 0x80, 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x01, 0x00, 0x10, 0x05,
387             0x10, 0x03, 0x40, 0x10, 0x03, 0x40, 0x09, 0x0f, 0x00, 0x0f
388         };
389
390         Plan plan(*vm, vector);
391         if (plan.result.size() != 1 || !plan.result[0]) {
392             dataLogLn("Module failed to compile correctly.");
393             CRASH();
394         }
395
396         // Test this doesn't crash.
397         CHECK_EQ(invoke<int>(*plan.result[0], { }), 11);
398     }
399
400     {
401         // Generated from: (module (func (export "add") (param $x i32) (param $y i32) (result i32) (return (i32.add (get_local $x) (get_local $y)))) )
402         Vector<uint8_t> vector = {
403             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
404             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x87, 0x80,
405             0x80, 0x80, 0x00, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x8e, 0x80, 0x80, 0x80, 0x00,
406             0x01, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x40, 0x09, 0x0f
407         };
408
409         Plan plan(*vm, vector);
410         if (plan.result.size() != 1 || !plan.result[0]) {
411             dataLogLn("Module failed to compile correctly.");
412             CRASH();
413         }
414
415         // Test this doesn't crash.
416         CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 1);
417         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(1) }), 101);
418         CHECK_EQ(invoke<int>(*plan.result[0], { box(-1), box(1)}), 0);
419         CHECK_EQ(invoke<int>(*plan.result[0], { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min());
420     }
421
422     {
423         // Generated from:
424         //    (module
425         //     (func (export "locals") (param $x i32) (result i32) (local $num i32)
426         //      (set_local $num (get_local $x))
427         //      (return (get_local $num))
428         //      )
429         //     )
430         Vector<uint8_t> vector = {
431             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
432             0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8a, 0x80, 0x80,
433             0x80, 0x00, 0x01, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x00, 0x00, 0x0a, 0x91, 0x80, 0x80,
434             0x80, 0x00, 0x01, 0x8b, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x14, 0x00, 0x15, 0x01, 0x14,
435             0x01, 0x09, 0x0f
436         };
437
438         Plan plan(*vm, vector);
439         if (plan.result.size() != 1 || !plan.result[0]) {
440             dataLogLn("Module failed to compile correctly.");
441             CRASH();
442         }
443
444         // Test this doesn't crash.
445         CHECK_EQ(invoke<int>(*plan.result[0], { box(0) }), 0);
446         CHECK_EQ(invoke<int>(*plan.result[0], { box(10) }), 10);
447     }
448
449     {
450         // Generated from:
451         //    (module
452         //     (func (export "sum") (param $x i32) (result i32) (local $y i32)
453         //      (set_local $y (i32.const 0))
454         //      (loop
455         //       (block
456         //        (br_if 0 (i32.eq (get_local $x) (i32.const 0)))
457         //        (set_local $y (i32.add (get_local $x) (get_local $y)))
458         //        (set_local $x (i32.sub (get_local $x) (i32.const 1)))
459         //        (br 1)
460         //        )
461         //       )
462         //      (return (get_local $y))
463         //      )
464         //     )
465         Vector<uint8_t> vector = {
466             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
467             0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x87, 0x80, 0x80,
468             0x80, 0x00, 0x01, 0x03, 0x73, 0x75, 0x6d, 0x00, 0x00, 0x0a, 0xae, 0x80, 0x80, 0x80, 0x00, 0x01,
469             0xa8, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x01, 0x02, 0x00, 0x01, 0x00,
470             0x14, 0x00, 0x10, 0x00, 0x4d, 0x07, 0x00, 0x14, 0x00, 0x14, 0x01, 0x40, 0x15, 0x01, 0x14, 0x00,
471             0x10, 0x01, 0x41, 0x15, 0x00, 0x06, 0x01, 0x0f, 0x0f, 0x14, 0x01, 0x09, 0x0f
472         };
473
474         Plan plan(*vm, vector);
475         if (plan.result.size() != 1 || !plan.result[0]) {
476             dataLogLn("Module failed to compile correctly.");
477             CRASH();
478         }
479
480         // Test this doesn't crash.
481         CHECK_EQ(invoke<int>(*plan.result[0], { box(0) }), 0);
482         CHECK_EQ(invoke<int>(*plan.result[0], { box(1) }), 1);
483         CHECK_EQ(invoke<int>(*plan.result[0], { box(2)}), 3);
484         CHECK_EQ(invoke<int>(*plan.result[0], { box(100) }), 5050);
485     }
486
487     {
488         // Generated from:
489         //    (module
490         //     (func (export "dumb-mult") (param $x i32) (param $y i32) (result i32) (local $total i32) (local $i i32) (local $j i32)
491         //      (set_local $total (i32.const 0))
492         //      (set_local $i (i32.const 0))
493         //      (block (loop
494         //              (br_if 1 (i32.eq (get_local $i) (get_local $x)))
495         //              (set_local $j (i32.const 0))
496         //              (set_local $i (i32.add (get_local $i) (i32.const 1)))
497         //              (loop
498         //               (br_if 1 (i32.eq (get_local $j) (get_local $y)))
499         //               (set_local $total (i32.add (get_local $total) (i32.const 1)))
500         //               (set_local $j (i32.add (get_local $j) (i32.const 1)))
501         //               (br 0)
502         //               )
503         //              ))
504         //      (return (get_local $total))
505         //      )
506         //     )
507         Vector<uint8_t> vector = {
508             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
509             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x8d, 0x80,
510             0x80, 0x80, 0x00, 0x01, 0x09, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6d, 0x75, 0x6c, 0x74, 0x00, 0x00,
511             0x0a, 0xc7, 0x80, 0x80, 0x80, 0x00, 0x01, 0xc1, 0x80, 0x80, 0x80, 0x00, 0x01, 0x03, 0x01, 0x10,
512             0x00, 0x15, 0x02, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00, 0x02, 0x00, 0x14, 0x03, 0x14, 0x00, 0x4d,
513             0x07, 0x01, 0x10, 0x00, 0x15, 0x04, 0x14, 0x03, 0x10, 0x01, 0x40, 0x15, 0x03, 0x02, 0x00, 0x14,
514             0x04, 0x14, 0x01, 0x4d, 0x07, 0x01, 0x14, 0x02, 0x10, 0x01, 0x40, 0x15, 0x02, 0x14, 0x04, 0x10,
515             0x01, 0x40, 0x15, 0x04, 0x06, 0x00, 0x0f, 0x0f, 0x0f, 0x14, 0x02, 0x09, 0x0f
516         };
517
518         Plan plan(*vm, vector);
519         if (plan.result.size() != 1 || !plan.result[0]) {
520             dataLogLn("Module failed to compile correctly.");
521             CRASH();
522         }
523
524         // Test this doesn't crash.
525         CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 0);
526         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(0) }), 0);
527         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(1) }), 2);
528         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(2) }), 2);
529         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(2) }), 4);
530         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(6) }), 12);
531         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(6) }), 600);
532         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(100) }), 10000);
533     }
534
535     {
536         // Generated from:
537         //    (module
538         //     (func "dumb-less-than" (param $x i32) (param $y i32) (result i32)
539         //      (loop
540         //       (block
541         //        (block
542         //         (br_if 0 (i32.eq (get_local $x) (get_local $y)))
543         //         (br 1)
544         //         )
545         //        (return (i32.const 0))
546         //        )
547         //       (block
548         //        (block
549         //         (br_if 0 (i32.eq (get_local $x) (i32.const 0)))
550         //         (br 1)
551         //         )
552         //        (return (i32.const 1))
553         //        )
554         //       (set_local $x (i32.sub (get_local $x) (i32.const 1)))
555         //       (br 0)
556         //       )
557         //       (unreachable)
558         //      )
559         //     )
560         Vector<uint8_t> vector = {
561             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
562             0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x07, 0x92, 0x80,
563             0x80, 0x80, 0x00, 0x01, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
564             0x68, 0x61, 0x6e, 0x00, 0x00, 0x0a, 0xb9, 0x80, 0x80, 0x80, 0x00, 0x01, 0xb3, 0x80, 0x80, 0x80,
565             0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x07, 0x00, 0x06,
566             0x01, 0x0f, 0x10, 0x00, 0x09, 0x0f, 0x01, 0x00, 0x01, 0x00, 0x14, 0x00, 0x10, 0x00, 0x4d, 0x07,
567             0x00, 0x06, 0x01, 0x0f, 0x10, 0x01, 0x09, 0x0f, 0x14, 0x00, 0x10, 0x01, 0x41, 0x15, 0x00, 0x06,
568             0x00, 0x0f, 0x00, 0x0f
569         };
570
571         Plan plan(*vm, vector);
572         if (plan.result.size() != 1 || !plan.result[0]) {
573             dataLogLn("Module failed to compile correctly.");
574             CRASH();
575         }
576
577         // Test this doesn't crash.
578         CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 1);
579         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(0) }), 0);
580         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(1) }), 0);
581         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(2) }), 1);
582         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(2) }), 0);
583         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(1) }), 0);
584         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(6) }), 1);
585         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(6) }), 0);
586     }
587
588 }
589
590 #endif // ENABLE(WEBASSEMBLY)
591
592 int main(int argc, char** argv)
593 {
594     CommandLine options(argc, argv);
595
596     if (options.m_runLEBTests)
597         runLEBTests();
598
599
600     if (options.m_runWASMTests) {
601 #if ENABLE(WEBASSEMBLY)
602         JSC::initializeThreading();
603         vm = &JSC::VM::create(JSC::LargeHeap).leakRef();
604         runWASMTests();
605 #else
606         dataLogLn("WASM is not enabled!");
607         return EXIT_FAILURE;
608 #endif // ENABLE(WEBASSEMBLY)
609     }
610
611     return EXIT_SUCCESS;
612 }
613