ca408960abf9d617a240ef800e5a358efd2850da
[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 "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, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80,
255             0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
256             0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x91, 0x80,
257             0x80, 0x00, 0x01, 0x00, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
258             0x68, 0x61, 0x6e, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x97, 0x80, 0x80, 0x00, 0x01, 0x92, 0x80, 0x80,
259             0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x03, 0x10, 0x00, 0x09, 0x01, 0x04, 0x10, 0x01, 0x09,
260             0x01, 0x0f, 0x0f
261         };
262
263         Plan plan(*vm, vector);
264         if (plan.result.size() != 1 || !plan.result[0]) {
265             dataLogLn("Module failed to compile correctly.");
266             CRASH();
267         }
268
269         // Test this doesn't crash.
270         CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 1);
271         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(0) }), 1);
272         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(1) }), 1);
273         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(2) }), 1);
274         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(2) }), 0);
275         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(1) }), 0);
276         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(6) }), 1);
277         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(6) }), 1);
278     }
279
280     {
281         // Generated from:
282         //    (module
283         //     (func "dumb-less-than" (param $x i32) (param $y i32) (result i32)
284         //      (loop
285         //       (if (i32.eq (get_local $x) (get_local $y))
286         //        (then (return (i32.const 0)))
287         //        (else (if (i32.eq (get_local $x) (i32.const 0))
288         //               (return (i32.const 1)))))
289         //       (set_local $x (i32.sub (get_local $x) (i32.const 1)))
290         //       (br 0)
291         //       )
292         //      )
293         //     )
294         Vector<uint8_t> vector = {
295             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80,
296             0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
297             0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x91, 0x80,
298             0x80, 0x00, 0x01, 0x00, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
299             0x68, 0x61, 0x6e, 0x04, 0x63, 0x6f, 0x64, 0x65, 0xaa, 0x80, 0x80, 0x00, 0x01, 0xa5, 0x80, 0x80,
300             0x00, 0x00, 0x02, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x03, 0x10, 0x00, 0x09, 0x01, 0x04, 0x14, 0x00,
301             0x10, 0x00, 0x4d, 0x03, 0x10, 0x01, 0x09, 0x01, 0x0f, 0x0f, 0x14, 0x00, 0x10, 0x01, 0x41, 0x15,
302             0x00, 0x06, 0x00, 0x00, 0x0f, 0x0f
303         };
304
305         Plan plan(*vm, vector);
306         if (plan.result.size() != 1 || !plan.result[0]) {
307             dataLogLn("Module failed to compile correctly.");
308             CRASH();
309         }
310
311         // Test this doesn't crash.
312         CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 1);
313         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(0) }), 0);
314         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(1) }), 0);
315         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(2) }), 1);
316         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(2) }), 0);
317         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(1) }), 0);
318         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(6) }), 1);
319         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(6) }), 0);
320     }
321
322     {
323         // Generated from:
324         //    (module
325         //     (func "dumb-less-than" (param $x i32) (param $y i32) (result i32)
326         //      (loop
327         //       (block
328         //        (block
329         //         (br_if 0 (i32.eq (get_local $x) (i32.const 0)))
330         //         (br 1)
331         //         )
332         //        (return (i32.const 1))
333         //        )
334         //       (block
335         //        (block
336         //         (br_if 0 (i32.eq (get_local $x) (get_local $y)))
337         //         (br 1)
338         //         )
339         //        (return (i32.const 0))
340         //        )
341         //       (set_local $x (i32.sub (get_local $x) (i32.const 1)))
342         //       (br 0)
343         //       )
344         //      )
345         //     )
346         Vector<uint8_t> vector = {
347             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80,
348             0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
349             0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x91, 0x80,
350             0x80, 0x00, 0x01, 0x00, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
351             0x68, 0x61, 0x6e, 0x04, 0x63, 0x6f, 0x64, 0x65, 0xb9, 0x80, 0x80, 0x00, 0x01, 0xb4, 0x80, 0x80,
352             0x00, 0x00, 0x02, 0x01, 0x01, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x07, 0x00, 0x00, 0x06, 0x00, 0x01,
353             0x0f, 0x10, 0x00, 0x09, 0x01, 0x0f, 0x01, 0x01, 0x14, 0x00, 0x10, 0x00, 0x4d, 0x07, 0x00, 0x00,
354             0x06, 0x00, 0x01, 0x0f, 0x10, 0x01, 0x09, 0x01, 0x0f, 0x14, 0x00, 0x10, 0x01, 0x41, 0x15, 0x00,
355             0x06, 0x00, 0x00, 0x0f, 0x0f
356         };
357
358         Plan plan(*vm, vector);
359         if (plan.result.size() != 1 || !plan.result[0]) {
360             dataLogLn("Module failed to compile correctly.");
361             CRASH();
362         }
363
364         // Test this doesn't crash.
365         CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 1);
366         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(0) }), 0);
367         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(1) }), 0);
368         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(2) }), 1);
369         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(2) }), 0);
370         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(1) }), 0);
371         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(6) }), 1);
372         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(6) }), 0);
373     }
374
375     {
376         // Generated from: (module (func "return-i32" (result i32) (return (i32.const 5))) )
377         Vector<uint8_t> vector = {
378             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x85, 0x80, 0x80,
379             0x00, 0x01, 0x40, 0x00, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x82,
380             0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x8d, 0x80, 0x80, 0x00,
381             0x01, 0x00, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x04, 0x63, 0x6f,
382             0x64, 0x65, 0x8b, 0x80, 0x80, 0x00, 0x01, 0x86, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x09, 0x01,
383             0x0f
384         };
385
386         Plan plan(*vm, vector);
387         if (plan.result.size() != 1 || !plan.result[0]) {
388             dataLogLn("Module failed to compile correctly.");
389             CRASH();
390         }
391
392         // Test this doesn't crash.
393         CHECK_EQ(invoke<int>(*plan.result[0], { }), 5);
394     }
395
396
397     {
398         // Generated from: (module (func "return-i32" (result i32) (return (i32.add (i32.const 5) (i32.const 6)))) )
399         Vector<uint8_t> vector = {
400             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x85, 0x80, 0x80,
401             0x00, 0x01, 0x40, 0x00, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x82,
402             0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x8d, 0x80, 0x80, 0x00,
403             0x01, 0x00, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x04, 0x63, 0x6f,
404             0x64, 0x65, 0x8e, 0x80, 0x80, 0x00, 0x01, 0x89, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x10, 0x06,
405             0x40, 0x09, 0x01, 0x0f
406         };
407
408         Plan plan(*vm, vector);
409         if (plan.result.size() != 1 || !plan.result[0]) {
410             dataLogLn("Module failed to compile correctly.");
411             CRASH();
412         }
413
414         // Test this doesn't crash.
415         CHECK_EQ(invoke<int>(*plan.result[0], { }), 11);
416     }
417     
418     {
419         // Generated from: (module (func "return-i32" (result i32) (return (i32.add (i32.add (i32.const 5) (i32.const 3)) (i32.const 3)))) )
420         Vector<uint8_t> vector = {
421             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x85, 0x80, 0x80,
422             0x00, 0x01, 0x40, 0x00, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x82,
423             0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x8d, 0x80, 0x80, 0x00,
424             0x01, 0x00, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x04, 0x63, 0x6f,
425             0x64, 0x65, 0x91, 0x80, 0x80, 0x00, 0x01, 0x8c, 0x80, 0x80, 0x00, 0x00, 0x10, 0x05, 0x10, 0x03,
426             0x40, 0x10, 0x03, 0x40, 0x09, 0x01, 0x0f
427         };
428
429         Plan plan(*vm, vector);
430         if (plan.result.size() != 1 || !plan.result[0]) {
431             dataLogLn("Module failed to compile correctly.");
432             CRASH();
433         }
434
435         // Test this doesn't crash.
436         CHECK_EQ(invoke<int>(*plan.result[0], { }), 11);
437     }
438
439     {
440         // Generated from: (module (func "return-i32" (result i32) (block (return (i32.add (i32.add (i32.const 5) (i32.const 3)) (i32.const 3))))) )
441         Vector<uint8_t> vector = {
442             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x85, 0x80, 0x80,
443             0x00, 0x01, 0x40, 0x00, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x82,
444             0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x8d, 0x80, 0x80, 0x00,
445             0x01, 0x00, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x69, 0x33, 0x32, 0x04, 0x63, 0x6f,
446             0x64, 0x65, 0x93, 0x80, 0x80, 0x00, 0x01, 0x8e, 0x80, 0x80, 0x00, 0x00, 0x01, 0x10, 0x05, 0x10,
447             0x03, 0x40, 0x10, 0x03, 0x40, 0x09, 0x01, 0x0f, 0x0f
448         };
449
450         Plan plan(*vm, vector);
451         if (plan.result.size() != 1 || !plan.result[0]) {
452             dataLogLn("Module failed to compile correctly.");
453             CRASH();
454         }
455
456         // Test this doesn't crash.
457         CHECK_EQ(invoke<int>(*plan.result[0], { }), 11);
458     }
459
460     {
461         // Generated from: (module (func $add (param $x i32) (param $y i32) (result i32) (return (i32.add (get_local $x) (get_local $y)))) )
462         Vector<uint8_t> vector = {
463             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80,
464             0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
465             0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x8e, 0x80, 0x80, 0x00,
466             0x01, 0x89, 0x80, 0x80, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x40, 0x09, 0x01, 0x0f
467         };
468
469         Plan plan(*vm, vector);
470         if (plan.result.size() != 1 || !plan.result[0]) {
471             dataLogLn("Module failed to compile correctly.");
472             CRASH();
473         }
474
475         // Test this doesn't crash.
476         CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 1);
477         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(1) }), 101);
478         CHECK_EQ(invoke<int>(*plan.result[0], { box(-1), box(1)}), 0);
479         CHECK_EQ(invoke<int>(*plan.result[0], { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min());
480     }
481
482     {
483         // Generated from:
484         //    (module
485         //     (func "locals" (param $x i32) (result i32) (local $num i32)
486         //      (set_local $num (get_local $x))
487         //      (return (get_local $num))
488         //      )
489         //     )
490         Vector<uint8_t> vector = {
491             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x86, 0x80, 0x80,
492             0x00, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
493             0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x89, 0x80, 0x80,
494             0x00, 0x01, 0x00, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x91,
495             0x80, 0x80, 0x00, 0x01, 0x8c, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x14, 0x00, 0x15, 0x01, 0x14,
496             0x01, 0x09, 0x01, 0x0f
497         };
498
499         Plan plan(*vm, vector);
500         if (plan.result.size() != 1 || !plan.result[0]) {
501             dataLogLn("Module failed to compile correctly.");
502             CRASH();
503         }
504
505         // Test this doesn't crash.
506         CHECK_EQ(invoke<int>(*plan.result[0], { box(0) }), 0);
507         CHECK_EQ(invoke<int>(*plan.result[0], { box(10) }), 10);
508     }
509
510     {
511         // Generated from:
512         //    (module
513         //     (func "dumb-mult" (param $x i32) (param $y i32) (result i32) (local $total i32) (local $i i32) (local $j i32)
514         //      (set_local $total (i32.const 0))
515         //      (set_local $i (i32.const 0))
516         //      (block
517         //       (loop
518         //        (br_if 1 (i32.eq (get_local $i) (get_local $x)))
519         //        (set_local $j (i32.const 0))
520         //        (set_local $i (i32.add (get_local $i) (i32.const 1)))
521         //        (loop
522         //         (br_if 1 (i32.eq (get_local $j) (get_local $y)))
523         //         (set_local $total (i32.add (get_local $total) (i32.const 1)))
524         //         (set_local $j (i32.add (get_local $j) (i32.const 1)))
525         //         (br 0)
526         //         )
527         //        )
528         //       )
529         //      (return (get_local $total))
530         //      )
531         //     )
532         Vector<uint8_t> vector = {
533             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x86, 0x80, 0x80,
534             0x00, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
535             0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x86, 0x80, 0x80,
536             0x00, 0x01, 0x00, 0x03, 0x73, 0x75, 0x6d, 0x04, 0x63, 0x6f, 0x64, 0x65, 0xae, 0x80, 0x80, 0x00,
537             0x01, 0xa9, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x01, 0x02, 0x01, 0x14, 0x00,
538             0x10, 0x00, 0x4d, 0x07, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x40, 0x15, 0x01, 0x14, 0x00, 0x10,
539             0x01, 0x41, 0x15, 0x00, 0x06, 0x00, 0x01, 0x0f, 0x0f, 0x14, 0x01, 0x09, 0x01, 0x0f
540         };
541
542         Plan plan(*vm, vector);
543         if (plan.result.size() != 1 || !plan.result[0]) {
544             dataLogLn("Module failed to compile correctly.");
545             CRASH();
546         }
547
548         // Test this doesn't crash.
549         CHECK_EQ(invoke<int>(*plan.result[0], { box(0) }), 0);
550         CHECK_EQ(invoke<int>(*plan.result[0], { box(1) }), 1);
551         CHECK_EQ(invoke<int>(*plan.result[0], { box(2)}), 3);
552         CHECK_EQ(invoke<int>(*plan.result[0], { box(100) }), 5050);
553     }
554
555     {
556         // Generated from:
557         //    (module
558         //     (func "dumb-mult" (param $x i32) (param $y i32) (result i32) (local $total i32) (local $i i32) (local $j i32)
559         //      (set_local $total (i32.const 0))
560         //      (set_local $i (i32.const 0))
561         //      (block (loop
562         //              (br_if 1 (i32.eq (get_local $i) (get_local $x)))
563         //              (set_local $j (i32.const 0))
564         //              (set_local $i (i32.add (get_local $i) (i32.const 1)))
565         //              (loop
566         //               (br_if 1 (i32.eq (get_local $j) (get_local $y)))
567         //               (set_local $total (i32.add (get_local $total) (i32.const 1)))
568         //               (set_local $j (i32.add (get_local $j) (i32.const 1)))
569         //               (br 0)
570         //               )
571         //              ))
572         //      (return (get_local $total))
573         //      )
574         //     )
575         Vector<uint8_t> vector = {
576             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80,
577             0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
578             0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x8c, 0x80,
579             0x80, 0x00, 0x01, 0x00, 0x09, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6d, 0x75, 0x6c, 0x74, 0x04, 0x63,
580             0x6f, 0x64, 0x65, 0xc7, 0x80, 0x80, 0x00, 0x01, 0xc2, 0x80, 0x80, 0x00, 0x01, 0x03, 0x01, 0x10,
581             0x00, 0x15, 0x02, 0x10, 0x00, 0x15, 0x03, 0x01, 0x02, 0x14, 0x03, 0x14, 0x00, 0x4d, 0x07, 0x00,
582             0x01, 0x10, 0x00, 0x15, 0x04, 0x14, 0x03, 0x10, 0x01, 0x40, 0x15, 0x03, 0x02, 0x14, 0x04, 0x14,
583             0x01, 0x4d, 0x07, 0x00, 0x01, 0x14, 0x02, 0x10, 0x01, 0x40, 0x15, 0x02, 0x14, 0x04, 0x10, 0x01,
584             0x40, 0x15, 0x04, 0x06, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x14, 0x02, 0x09, 0x01, 0x0f
585         };
586
587         Plan plan(*vm, vector);
588         if (plan.result.size() != 1 || !plan.result[0]) {
589             dataLogLn("Module failed to compile correctly.");
590             CRASH();
591         }
592
593         // Test this doesn't crash.
594         CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 0);
595         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(0) }), 0);
596         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(1) }), 2);
597         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(2) }), 2);
598         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(2) }), 4);
599         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(6) }), 12);
600         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(6) }), 600);
601         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(100) }), 10000);
602     }
603
604     {
605         // Generated from:
606         //    (module
607         //     (func "dumb-less-than" (param $x i32) (param $y i32) (result i32)
608         //      (loop
609         //       (block
610         //        (block
611         //         (br_if 0 (i32.eq (get_local $x) (i32.const 0)))
612         //         (br 1)
613         //         )
614         //        (return (i32.const 1))
615         //        )
616         //       (block
617         //        (block
618         //         (br_if 0 (i32.eq (get_local $x) (get_local $y)))
619         //         (br 1)
620         //         )
621         //        (return (i32.const 0))
622         //        )
623         //       (set_local $x (i32.sub (get_local $x) (i32.const 1)))
624         //       (br 0)
625         //       )
626         //      )
627         //     )
628         Vector<uint8_t> vector = {
629             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80,
630             0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
631             0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x91, 0x80,
632             0x80, 0x00, 0x01, 0x00, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74,
633             0x68, 0x61, 0x6e, 0x04, 0x63, 0x6f, 0x64, 0x65, 0xb9, 0x80, 0x80, 0x00, 0x01, 0xb4, 0x80, 0x80,
634             0x00, 0x00, 0x02, 0x01, 0x01, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x07, 0x00, 0x00, 0x06, 0x00, 0x01,
635             0x0f, 0x10, 0x00, 0x09, 0x01, 0x0f, 0x01, 0x01, 0x14, 0x00, 0x10, 0x00, 0x4d, 0x07, 0x00, 0x00,
636             0x06, 0x00, 0x01, 0x0f, 0x10, 0x01, 0x09, 0x01, 0x0f, 0x14, 0x00, 0x10, 0x01, 0x41, 0x15, 0x00,
637             0x06, 0x00, 0x00, 0x0f, 0x0f
638         };
639
640         Plan plan(*vm, vector);
641         if (plan.result.size() != 1 || !plan.result[0]) {
642             dataLogLn("Module failed to compile correctly.");
643             CRASH();
644         }
645
646         // Test this doesn't crash.
647         CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 1);
648         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(0) }), 0);
649         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(1) }), 0);
650         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(2) }), 1);
651         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(2) }), 0);
652         CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(1) }), 0);
653         CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(6) }), 1);
654         CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(6) }), 0);
655     }
656
657 }
658
659 #endif // ENABLE(WEBASSEMBLY)
660
661 int main(int argc, char** argv)
662 {
663     CommandLine options(argc, argv);
664
665     if (options.m_runLEBTests)
666         runLEBTests();
667
668
669     if (options.m_runWASMTests) {
670 #if ENABLE(WEBASSEMBLY)
671         JSC::initializeThreading();
672         vm = &JSC::VM::create(JSC::LargeHeap).leakRef();
673         runWASMTests();
674 #else
675         dataLogLn("WASM is not enabled!");
676         return EXIT_FAILURE;
677 #endif // ENABLE(WEBASSEMBLY)
678     }
679
680     return EXIT_SUCCESS;
681 }
682