quick and dirty pure lua webassembly interpreter
1local constants = {}
2
3constants.I32_MAX = (1 << 32) - 1
4
5constants.WASM_PAGE_SIZE = 65536
6constants.MAX_PAGES = 65536
7
8constants.opcodes = {
9-- Control
10 OP_UNREACHABLE = 0x00,
11 OP_NOP = 0x01,
12 OP_BLOCK = 0x02,
13 OP_LOOP = 0x03,
14 OP_IF = 0x04,
15 OP_ELSE = 0x05,
16 OP_END = 0x0B,
17 OP_BR = 0x0C,
18 OP_BR_IF = 0x0D,
19 OP_BR_TABLE = 0x0E,
20 OP_RETURN = 0x0F,
21 OP_CALL = 0x10,
22 OP_CALL_INDIRECT = 0x11,
23-- Parametric
24 OP_DROP = 0x1A,
25 OP_SELECT = 0x1B,
26-- Variable
27 OP_LOCAL_GET = 0x20,
28 OP_LOCAL_SET = 0x21,
29 OP_LOCAL_TEE = 0x22,
30 OP_GLOBAL_GET = 0x23,
31 OP_GLOBAL_SET = 0x24,
32-- Memory
33 OP_I32_LOAD = 0x28,
34 OP_I64_LOAD = 0x29,
35 OP_F32_LOAD = 0x2A,
36 OP_F64_LOAD = 0x2B,
37 OP_I32_LOAD8_S = 0x2C,
38 OP_I32_LOAD8_U = 0x2D,
39 OP_I32_LOAD16_S = 0x2E,
40 OP_I32_LOAD16_U = 0x2F,
41 OP_I64_LOAD8_S = 0x30,
42 OP_I64_LOAD8_U = 0x31,
43 OP_I64_LOAD16_S = 0x32,
44 OP_I64_LOAD16_U = 0x33,
45 OP_I64_LOAD32_S = 0x34,
46 OP_I64_LOAD32_U = 0x35,
47 OP_I32_STORE = 0x36,
48 OP_I64_STORE = 0x37,
49 OP_F32_STORE = 0x38,
50 OP_F64_STORE = 0x39,
51 OP_I32_STORE8 = 0x3A,
52 OP_I32_STORE16 = 0x3B,
53 OP_I64_STORE8 = 0x3C,
54 OP_I64_STORE16 = 0x3D,
55 OP_I64_STORE32 = 0x3E,
56 OP_MEMORY_SIZE = 0x3F,
57 OP_MEMORY_GROW = 0x40,
58-- Numeric Constants
59 OP_I32_CONST = 0x41,
60 OP_I64_CONST = 0x42,
61 OP_F32_CONST = 0x43,
62 OP_F64_CONST = 0x44,
63-- Numeric Operations
64-- i32 comparisons
65 OP_I32_EQZ = 0x45,
66 OP_I32_EQ = 0x46,
67 OP_I32_NE = 0x47,
68 OP_I32_LT_S = 0x48,
69 OP_I32_LT_U = 0x49,
70 OP_I32_GT_S = 0x4A,
71 OP_I32_GT_U = 0x4B,
72 OP_I32_LE_S = 0x4C,
73 OP_I32_LE_U = 0x4D,
74 OP_I32_GE_S = 0x4E,
75 OP_I32_GE_U = 0x4F,
76-- i64 comparisons
77 OP_I64_EQZ = 0x50,
78 OP_I64_EQ = 0x51,
79 OP_I64_NE = 0x52,
80 OP_I64_LT_S = 0x53,
81 OP_I64_LT_U = 0x54,
82 OP_I64_GT_S = 0x55,
83 OP_I64_GT_U = 0x56,
84 OP_I64_LE_S = 0x57,
85 OP_I64_LE_U = 0x58,
86 OP_I64_GE_S = 0x59,
87 OP_I64_GE_U = 0x5A,
88-- f32 comparisons
89 OP_F32_EQ = 0x5B,
90 OP_F32_NE = 0x5C,
91 OP_F32_LT = 0x5D,
92 OP_F32_GT = 0x5E,
93 OP_F32_LE = 0x5F,
94 OP_F32_GE = 0x60,
95-- f64 comparisons
96 OP_F64_EQ = 0x61,
97 OP_F64_NE = 0x62,
98 OP_F64_LT = 0x63,
99 OP_F64_GT = 0x64,
100 OP_F64_LE = 0x65,
101 OP_F64_GE = 0x66,
102-- i32 operations
103 OP_I32_CLZ = 0x67,
104 OP_I32_CTZ = 0x68,
105 OP_I32_POPCNT = 0x69,
106 OP_I32_ADD = 0x6A,
107 OP_I32_SUB = 0x6B,
108 OP_I32_MUL = 0x6C,
109 OP_I32_DIV_S = 0x6D,
110 OP_I32_DIV_U = 0x6E,
111 OP_I32_REM_S = 0x6F,
112 OP_I32_REM_U = 0x70,
113 OP_I32_AND = 0x71,
114 OP_I32_OR = 0x72,
115 OP_I32_XOR = 0x73,
116 OP_I32_SHL = 0x74,
117 OP_I32_SHR_S = 0x75,
118 OP_I32_SHR_U = 0x76,
119 OP_I32_ROTL = 0x77,
120 OP_I32_ROTR = 0x78,
121-- i64 operations
122 OP_I64_CLZ = 0x79,
123 OP_I64_CTZ = 0x7A,
124 OP_I64_POPCNT = 0x7B,
125 OP_I64_ADD = 0x7C,
126 OP_I64_SUB = 0x7D,
127 OP_I64_MUL = 0x7E,
128 OP_I64_DIV_S = 0x7F,
129 OP_I64_DIV_U = 0x80,
130 OP_I64_REM_S = 0x81,
131 OP_I64_REM_U = 0x82,
132 OP_I64_AND = 0x83,
133 OP_I64_OR = 0x84,
134 OP_I64_XOR = 0x85,
135 OP_I64_SHL = 0x86,
136 OP_I64_SHR_S = 0x87,
137 OP_I64_SHR_U = 0x88,
138 OP_I64_ROTL = 0x89,
139 OP_I64_ROTR = 0x8A,
140-- f32 operations
141 OP_F32_ABS = 0x8B,
142 OP_F32_NEG = 0x8C,
143 OP_F32_CEIL = 0x8D,
144 OP_F32_FLOOR = 0x8E,
145 OP_F32_TRUNC = 0x8F,
146 OP_F32_NEAREST = 0x90,
147 OP_F32_SQRT = 0x91,
148 OP_F32_ADD = 0x92,
149 OP_F32_SUB = 0x93,
150 OP_F32_MUL = 0x94,
151 OP_F32_DIV = 0x95,
152 OP_F32_MIN = 0x96,
153 OP_F32_MAX = 0x97,
154 OP_F32_COPYSIGN = 0x98,
155-- f64 operations
156 OP_F64_ABS = 0x99,
157 OP_F64_NEG = 0x9A,
158 OP_F64_CEIL = 0x9B,
159 OP_F64_FLOOR = 0x9C,
160 OP_F64_TRUNC = 0x9D,
161 OP_F64_NEAREST = 0x9E,
162 OP_F64_SQRT = 0x9F,
163 OP_F64_ADD = 0xA0,
164 OP_F64_SUB = 0xA1,
165 OP_F64_MUL = 0xA2,
166 OP_F64_DIV = 0xA3,
167 OP_F64_MIN = 0xA4,
168 OP_F64_MAX = 0xA5,
169 OP_F64_COPYSIGN = 0xA6,
170-- conversions
171 OP_I32_WRAP_I64 = 0xA7,
172 OP_I32_TRUNC_F32_S = 0xA8,
173 OP_I32_TRUNC_F32_U = 0xA9,
174 OP_I32_TRUNC_F64_S = 0xAA,
175 OP_I32_TRUNC_F64_U = 0xAB,
176 OP_I64_EXTEND_I32_S = 0xAC,
177 OP_I64_EXTEND_I32_U = 0xAD,
178 OP_I64_TRUNC_F32_S = 0xAE,
179 OP_I64_TRUNC_F32_U = 0xAF,
180 OP_I64_TRUNC_F64_S = 0xB0,
181 OP_I64_TRUNC_F64_U = 0xB1,
182 OP_F32_CONVERT_I32_S = 0xB2,
183 OP_F32_CONVERT_I32_U = 0xB3,
184 OP_F32_CONVERT_I64_S = 0xB4,
185 OP_F32_CONVERT_I64_U = 0xB5,
186 OP_F32_DEMOTE_F64 = 0xB6,
187 OP_F64_CONVERT_I32_S = 0xB7,
188 OP_F64_CONVERT_I32_U = 0xB8,
189 OP_F64_CONVERT_I64_S = 0xB9,
190 OP_F64_CONVERT_I64_U = 0xBA,
191 OP_F64_PROMOTE_F32 = 0xBB,
192 OP_I32_REINTERPRET_F32 = 0xBC,
193 OP_I64_REINTERPRET_F64 = 0xBD,
194 OP_F32_REINTERPRET_I32 = 0xBE,
195 OP_F64_REINTERPRET_I64 = 0xBF,
196-- sign extension
197 OP_I32_EXTEND8_S = 0xC0,
198 OP_I32_EXTEND16_S = 0xC1,
199 OP_I64_EXTEND8_S = 0xC2,
200 OP_I64_EXTEND16_S = 0xC3,
201 OP_I64_EXTEND32_S = 0xC4,
202}
203
204local c = constants.opcodes
205
206constants.blockOpcodes = {
207 [c.OP_BLOCK] = true,
208 [c.OP_LOOP] = true,
209 [c.OP_IF] = true,
210}
211
212-- Operand types of each instruction.
213-- Types are represented as an array where each element represents an operand:
214-- * "b": byte
215-- * "u": u32
216-- * "d": u32 index (needs to be incremented by 1 to account for lua 1-indexed arrays)
217-- (used for all index types except label indices, and _not_ memory offsets)
218-- * "U": u64
219-- * "i": i32
220-- * "I": i64
221-- * "V" before one of these types represents a vector of that type.
222-- Opcodes that are not in this table are assumed to take no operands.
223constants.operandTypes = {
224-- control
225 [c.OP_BLOCK] = {"b"},
226 [c.OP_LOOP] = {"b"},
227 [c.OP_IF] = {"b"},
228 [c.OP_BR] = {"u"},
229 [c.OP_BR_IF] = {"u"},
230 [c.OP_BR_TABLE] = {"Vu", "u"},
231 [c.OP_CALL] = {"d"},
232 [c.OP_CALL_INDIRECT] = {"d", "b"},
233-- parametric
234-- variable
235 [c.OP_LOCAL_GET] = {"d"},
236 [c.OP_LOCAL_SET] = {"d"},
237 [c.OP_LOCAL_TEE] = {"d"},
238 [c.OP_GLOBAL_GET] = {"d"},
239 [c.OP_GLOBAL_SET] = {"d"},
240-- memory
241 [c.OP_I32_LOAD] = {"u", "u"},
242 [c.OP_I64_LOAD] = {"u", "u"},
243 [c.OP_I32_LOAD8_S] = {"u", "u"},
244 [c.OP_I32_LOAD8_U] = {"u", "u"},
245 [c.OP_I32_LOAD16_S] = {"u", "u"},
246 [c.OP_I32_LOAD16_U] = {"u", "u"},
247 [c.OP_I64_LOAD8_S] = {"u", "u"},
248 [c.OP_I64_LOAD16_S] = {"u", "u"},
249 [c.OP_I64_LOAD16_U] = {"u", "u"},
250 [c.OP_I64_LOAD32_S] = {"u", "u"},
251 [c.OP_I64_LOAD32_U] = {"u", "u"},
252 [c.OP_I32_STORE] = {"u", "u"},
253 [c.OP_I64_STORE] = {"u", "u"},
254 [c.OP_I32_STORE8] = {"u", "u"},
255 [c.OP_I32_STORE16] = {"u", "u"},
256 [c.OP_I64_STORE8] = {"u", "u"},
257 [c.OP_I64_STORE16] = {"u", "u"},
258 [c.OP_I64_STORE32] = {"u", "u"},
259 [c.OP_MEMORY_SIZE] = {"b"},
260 [c.OP_MEMORY_GROW] = {"b"},
261-- constants
262 [c.OP_I32_CONST] = {"i"},
263 [c.OP_I64_CONST] = {"I"},
264-- all remaining instructions are arithmetic instructions with no operands
265}
266
267-- Lengths of each instruction
268-- (zero represents variable length)
269constants.ilengths = {
270-- control
271 [c.OP_UNREACHABLE] = 1,
272 [c.OP_NOP] = 1,
273 [c.OP_BLOCK] = 0,
274 [c.OP_LOOP] = 0,
275 [c.OP_IF] = 0,
276 [c.OP_ELSE] = 0,
277 [c.OP_END] = 1,
278 [c.OP_BR] = 2,
279 [c.OP_BR_IF] = 2,
280 [c.OP_BR_TABLE] = 3,
281 [c.OP_RETURN] = 1,
282 [c.OP_CALL] = 2,
283 [c.OP_CALL_INDIRECT] = 3,
284-- parametric
285 [c.OP_DROP] = 1,
286 [c.OP_SELECT] = 1,
287-- variable
288 [c.OP_LOCAL_GET] = 2,
289 [c.OP_LOCAL_SET] = 2,
290 [c.OP_LOCAL_TEE] = 2,
291 [c.OP_GLOBAL_GET] = 2,
292 [c.OP_GLOBAL_SET] = 2,
293-- memory
294 [c.OP_I32_LOAD] = 3,
295 [c.OP_I64_LOAD] = 3,
296 -- [float instrs]
297 [c.OP_I32_LOAD8_S] = 3,
298 [c.OP_I32_LOAD8_U] = 3,
299 [c.OP_I32_LOAD16_S] = 3,
300 [c.OP_I32_LOAD16_U] = 3,
301 [c.OP_I64_LOAD8_S] = 3,
302 [c.OP_I64_LOAD8_U] = 3,
303 [c.OP_I64_LOAD16_S] = 3,
304 [c.OP_I64_LOAD16_U] = 3,
305 [c.OP_I64_LOAD32_S] = 3,
306 [c.OP_I64_LOAD32_U] = 3,
307 [c.OP_I32_STORE] = 3,
308 [c.OP_I64_STORE] = 3,
309 -- [float instrs]
310 [c.OP_I32_STORE8] = 3,
311 [c.OP_I32_STORE16] = 3,
312 [c.OP_I64_STORE8] = 3,
313 [c.OP_I64_STORE16] = 3,
314 [c.OP_I64_STORE32] = 3,
315 [c.OP_MEMORY_SIZE] = 2,
316 [c.OP_MEMORY_GROW] = 2,
317-- constants
318 [c.OP_I32_CONST] = 2,
319 [c.OP_I64_CONST] = 2,
320 -- [float consts]
321-- i32 comparisons
322 [c.OP_I32_EQZ] = 1,
323 [c.OP_I32_EQ] = 1,
324 [c.OP_I32_NE] = 1,
325 [c.OP_I32_LT_S] = 1,
326 [c.OP_I32_LT_U] = 1,
327 [c.OP_I32_GT_S] = 1,
328 [c.OP_I32_GT_U] = 1,
329 [c.OP_I32_LE_S] = 1,
330 [c.OP_I32_LE_U] = 1,
331 [c.OP_I32_GE_S] = 1,
332 [c.OP_I32_GE_U] = 1,
333-- i64 comparisons
334 [c.OP_I64_EQZ] = 1,
335 [c.OP_I64_EQ] = 1,
336 [c.OP_I64_NE] = 1,
337 [c.OP_I64_LT_S] = 1,
338 [c.OP_I64_LT_U] = 1,
339 [c.OP_I64_GT_S] = 1,
340 [c.OP_I64_GT_U] = 1,
341 [c.OP_I64_LE_S] = 1,
342 [c.OP_I64_LE_U] = 1,
343 [c.OP_I64_GE_S] = 1,
344 [c.OP_I64_GE_U] = 1,
345-- [float comparisons]
346-- i32 operations
347 [c.OP_I32_CLZ] = 1,
348 [c.OP_I32_CTZ] = 1,
349 [c.OP_I32_POPCNT] = 1,
350 [c.OP_I32_ADD] = 1,
351 [c.OP_I32_SUB] = 1,
352 [c.OP_I32_MUL] = 1,
353 [c.OP_I32_DIV_S] = 1,
354 [c.OP_I32_DIV_U] = 1,
355 [c.OP_I32_REM_S] = 1,
356 [c.OP_I32_REM_U] = 1,
357 [c.OP_I32_AND] = 1,
358 [c.OP_I32_OR] = 1,
359 [c.OP_I32_XOR] = 1,
360 [c.OP_I32_SHL] = 1,
361 [c.OP_I32_SHR_S] = 1,
362 [c.OP_I32_SHR_U] = 1,
363 [c.OP_I32_ROTL] = 1,
364 [c.OP_I32_ROTR] = 1,
365-- i64 operations
366 [c.OP_I64_CLZ] = 1,
367 [c.OP_I64_CTZ] = 1,
368 [c.OP_I64_POPCNT] = 1,
369 [c.OP_I64_ADD] = 1,
370 [c.OP_I64_SUB] = 1,
371 [c.OP_I64_MUL] = 1,
372 [c.OP_I64_DIV_S] = 1,
373 [c.OP_I64_DIV_U] = 1,
374 [c.OP_I64_REM_S] = 1,
375 [c.OP_I64_REM_U] = 1,
376 [c.OP_I64_AND] = 1,
377 [c.OP_I64_OR] = 1,
378 [c.OP_I64_XOR] = 1,
379 [c.OP_I64_SHL] = 1,
380 [c.OP_I64_SHR_S] = 1,
381 [c.OP_I64_SHR_U] = 1,
382 [c.OP_I64_ROTL] = 1,
383 [c.OP_I64_ROTR] = 1,
384 -- [float operations]
385-- conversions
386 [c.OP_I32_WRAP_I64] = 1,
387 -- [float stuff]
388 [c.OP_I64_EXTEND_I32_S] = 1,
389 [c.OP_I64_EXTEND_I32_U] = 1,
390 -- [float stuff]
391-- sign extension
392 [c.OP_I32_EXTEND8_S] = 1,
393 [c.OP_I32_EXTEND16_S] = 1,
394 [c.OP_I64_EXTEND8_S] = 1,
395 [c.OP_I64_EXTEND16_S] = 1,
396 [c.OP_I64_EXTEND32_S] = 1,
397}
398
399constants.valtypes = {
400 VTY_I32 = 0x7F,
401 VTY_I64 = 0x7E,
402 VTY_F32 = 0x7D,
403 VTY_F64 = 0x7C,
404}
405
406constants.blocktypes = {
407 BTY_NONE = 0x40,
408 BTY_I32 = constants.valtypes.VTY_I32,
409 BTY_I64 = constants.valtypes.VTY_I64,
410 BTY_F32 = constants.valtypes.VTY_F32,
411 BTY_F64 = constants.valtypes.VTY_F64,
412
413}
414
415constants.sectionIds = {
416 SECT_CUSTOM = 0,
417 SECT_TYPE = 1,
418 SECT_IMPORT = 2,
419 SECT_FUNC = 3,
420 SECT_TABLE = 4,
421 SECT_MEM = 5,
422 SECT_GLOBAL = 6,
423 SECT_EXPORT = 7,
424 SECT_START = 8,
425 SECT_ELEM = 9,
426 SECT_CODE = 10,
427 SECT_DATA = 11,
428}
429
430return constants