···2233frame.StackFrame = {
44 funcIndex = 0,
55- locals = {},
65 pc = 0, -- program counter
76}
8798function frame.StackFrame:new(funcIndex)
1010- local f = {}
99+ local f = {
1010+ locals = {},
1111+ labelStack = {},
1212+ }
1113 setmetatable(f, {__index = self})
1214 f.funcIndex = funcIndex
1315 return f
+2-2
intutil.lua
···3838 return n
3939end
40404141-function intutil.fromle64(tab, idx, n)
4141+function intutil.tole64(tab, idx, n)
4242 tab[idx] = n & 0xFF
4343 tab[idx+1] = (n >> 8) & 0xFF
4444 tab[idx+2] = (n >> 16) & 0xFF
···9999 if (shift < bits) and ((tab[idx+len-1] & 0x40) ~= 0) then
100100 result = result | (((1 << bits) - 1) << shift)
101101 end
102102- return len, result
102102+ return len, result & ((1 << bits) - 1)
103103end
104104105105return intutil
+18-23
memory.lua
···2233local constants = require("constants")
4455-function memory.new(pages)
66- local m = {
77- mem = {},
88- pages = pages,
99- }
1010- setmetatable(m, {
1111- __index = function(self, key)
1212- if key >= (self.pages * constants.WASM_PAGE_SIZE) then
1313- error("out of bounds memory access")
1414- end
1515- return self.mem[key] or 0
1616- end,
1717- __newindex = function(self, key, value)
1818- if key < (self.pages * constants.WASM_PAGE_SIZE) then
1919- self.mem[key] = value
2020- else
2121- error("out of bounds memory access")
2222- end
2323- end,
2424- __len = function(self)
2525- return self.pages
2626- end,
2727- })
55+memory.Memory = {
66+ pages = 0,
77+ maxpages = -1,
88+}
99+1010+function memory.Memory:new(pages)
1111+ local m = {}
1212+ setmetatable(m, {__index = self})
1313+ m:grow(pages)
2814 return m
1515+end
1616+1717+function memory.Memory:grow(pages)
1818+ local initStart = self.pages * constants.WASM_PAGE_SIZE
1919+ local initEnd = ((self.pages + pages) * constants.WASM_PAGE_SIZE) - 1
2020+ for i = initStart, initEnd do
2121+ self[i] = 0
2222+ end
2323+ self.pages = self.pages + pages
2924end
30253126return memory
+36-6
ops.lua
···148148 return a << b
149149end
150150151151-function ops.i64_shr_s(a, b)
151151+function ops.i64_shr_u(a, b)
152152 return a >> b
153153end
154154···337337 return (a << b) & constants.I32_MAX
338338end
339339340340-function ops.i32_shr_s(a, b)
341341- a = intutil.signexti32(a)
342342- b = intutil.signexti32(b)
340340+function ops.i32_shr_u(a, b)
343341 return (a >> b) & constants.I32_MAX
344342end
345343346346-function ops.i32_shr_u(a, b)
347347- return (a >> b) & constants.I32_MAX
344344+function ops.i32_shr_s(a, b)
345345+ if b >= 32 then
346346+ if (a & 0x80000000) == 0 then
347347+ return 0
348348+ else
349349+ return constants.I32_MAX
350350+ end
351351+ end
352352+353353+ local result = a >> b
354354+ if (a & 0x80000000) ~= 0 then
355355+ result = result | (((1 << b) - 1) << (32 - b))
356356+ end
357357+ return result
348358end
349359350360function ops.i32_rotl(a, b)
···369379370380function ops.i64_extend_i32_u(a)
371381 return a
382382+end
383383+384384+function ops.i32_extend8_s(a)
385385+ return intutil.signexti8(a) & constants.I32_MAX
386386+end
387387+388388+function ops.i32_extend16_s(a)
389389+ return intutil.signexti16(a) & constants.I32_MAX
390390+end
391391+392392+function ops.i64_extend8_s(a)
393393+ return intutil.signexti8(a)
394394+end
395395+396396+function ops.i64_extend16_s(a)
397397+ return intutil.signexti16(a)
398398+end
399399+400400+function ops.i64_extend32_s(a)
401401+ return intutil.signexti32(a)
372402end
373403374404return ops
+199-70
wasmlib.lua
···14141515wasmlib.VM = {
1616 numImportedFuncs = 0,
1717- stack = {},
1818- stackFrames = {},
1919- labelStack = {},
2020- functions = {},
2121- types = {},
2222- memory = {},
2323- globals = {},
2424- imports = {},
2517}
26182719function wasmlib.VM:new()
2828- local vm = {}
2020+ local vm = {
2121+ stack = {},
2222+ stackFrames = {},
2323+ functions = {},
2424+ table = {},
2525+ types = {},
2626+ memory = {},
2727+ globals = {},
2828+ imports = {},
2929+ exports = {},
3030+ }
2931 setmetatable(vm, {__index = self})
3032 return vm
3133end
···68706971function wasmlib.VM:local_get()
7072 local localIdx = self:nextArg()
7171- local localVal = self:curLocals()[localIdx]
7272- if localVal == nil then
7373- error("read uninitialised or out of bounds local")
7474- end
7373+ local localVal = self:curLocals()[localIdx] or 0 -- FIXME bounds check
7574 table.insert(self.stack, localVal)
7675end
7776···107106 self:invoke(funcIdx)
108107end
109108109109+function wasmlib.VM:call_indirect()
110110+ local tabOffset = table.remove(self.stack)
111111+ self:nextArg() -- FIXME ignoring typeIdx
112112+ self:nextArg() -- always zero in wasm 1.0
113113+ local funcIdx = self.table[tabOffset]
114114+ if funcIdx == nil then
115115+ error("invalid call_indirect")
116116+ end
117117+ self:invoke(funcIdx)
118118+end
119119+110120function wasmlib.VM:memory_size()
111121 if self:nextArg() ~= 0 then
112122 error("memory.size operand must be zero")
113123 end
114124115115- return #self.memory
125125+ table.insert(self.stack, self.memory.pages)
116126end
117127118128function wasmlib.VM:memory_grow()
···122132123133 local amount = table.remove(self.stack)
124134 if (
125125- (self.memory.maxpages ~= nil) and (#self.memory + amount > self.memory.maxpages)
126126- ) or (#self.memory + amount > constants.I32_MAX)
135135+ (self.memory.maxpages > 0) and (self.memory.pages + amount > self.memory.maxpages)
136136+ ) or (self.memory.pages + amount > constants.MAX_PAGES)
127137 then
128138 table.insert(self.stack, constants.I32_MAX) -- i32 -1
129139 else
130130- self.memory.pages = #self.memory + amount
131131- table.insert(self.stack, #self.memory)
140140+ table.insert(self.stack, self.memory.pages)
141141+ self.memory:grow(amount)
132142 end
133143end
134144···137147 local offset = self:nextArg()
138148 local argument = table.remove(self.stack)
139149 local value = intutil.fromle32(self.memory, offset + argument)
150150+ trace("i32 loaded "..value.." from "..(offset+argument))
140151 table.insert(self.stack, value)
141152end
142153···145156 local offset = self:nextArg()
146157 local argument = table.remove(self.stack)
147158 local value = intutil.fromle64(self.memory, offset + argument)
159159+ trace("i64 loaded "..value.." from "..(offset+argument))
148160 table.insert(self.stack, value)
149161end
150162···153165 local offset = self:nextArg()
154166 local argument = table.remove(self.stack)
155167 local value = intutil.signexti8(self.memory[offset + argument]) & constants.I32_MAX
168168+ trace("i32 8s loaded "..value.." from "..(offset+argument))
156169 table.insert(self.stack, value)
157170end
158171···161174 local offset = self:nextArg()
162175 local argument = table.remove(self.stack)
163176 local value = self.memory[offset + argument]
177177+ trace("i32 8u loaded "..value.." from "..(offset+argument))
164178 table.insert(self.stack, value)
165179end
166180···169183 local offset = self:nextArg()
170184 local argument = table.remove(self.stack)
171185 local value = intutil.signexti16(intutil.fromle16(self.memory, offset + argument)) & constants.I32_MAX
186186+ trace("i32 16s loaded "..value.." from "..(offset+argument))
172187 table.insert(self.stack, value)
173188end
174189···177192 local offset = self:nextArg()
178193 local argument = table.remove(self.stack)
179194 local value = intutil.fromle16(self.memory, offset + argument)
195195+ trace("i32 16u loaded "..value.." from "..(offset+argument))
180196 table.insert(self.stack, value)
181197end
182198···185201 local offset = self:nextArg()
186202 local argument = table.remove(self.stack)
187203 local value = intutil.signexti8(self.memory[offset + argument])
204204+ trace("i64 8s loaded "..value.." from "..(offset+argument))
188205 table.insert(self.stack, value)
189206end
190207···193210 local offset = self:nextArg()
194211 local argument = table.remove(self.stack)
195212 local value = self.memory[offset + argument]
213213+ trace("i64 8u loaded "..value.." from "..(offset+argument))
196214 table.insert(self.stack, value)
197215end
198216···201219 local offset = self:nextArg()
202220 local argument = table.remove(self.stack)
203221 local value = intutil.signexti16(intutil.fromle16(self.memory, offset + argument))
222222+ trace("i64 16s loaded "..value.." from "..(offset+argument))
204223 table.insert(self.stack, value)
205224end
206225···209228 local offset = self:nextArg()
210229 local argument = table.remove(self.stack)
211230 local value = intutil.fromle16(self.memory, offset + argument)
231231+ trace("i64 16u loaded "..value.." from "..(offset+argument))
212232 table.insert(self.stack, value)
213233end
214234···217237 local offset = self:nextArg()
218238 local argument = table.remove(self.stack)
219239 local value = intutil.signexti32(intutil.fromle32(self.memory, offset + argument))
240240+ trace("i64 32s loaded "..value.." from "..(offset+argument))
220241 table.insert(self.stack, value)
221242end
222243···225246 local offset = self:nextArg()
226247 local argument = table.remove(self.stack)
227248 local value = intutil.fromle32(self.memory, offset + argument)
228228- table.insert(self.stack, value)
229229-end
230230-231231-function wasmlib.VM:i64_load()
232232- self:nextArg() -- alignment, ignored for now
233233- local offset = self:nextArg()
234234- local argument = table.remove(self.stack)
235235- local value = intutil.signexti16(intutil.fromle16(self.memory, offset + argument))
249249+ trace("i64 32u loaded "..value.." from "..(offset+argument))
236250 table.insert(self.stack, value)
237251end
238252239253function wasmlib.VM:i32_store()
240254 self:nextArg() -- alignment, ignored for now
241255 local offset = self:nextArg()
256256+ local value = table.remove(self.stack)
242257 local argument = table.remove(self.stack)
243243- local value = table.remove(self.stack)
258258+ trace("i32 stored "..value.." at "..(offset+argument))
244259 intutil.tole32(self.memory, offset + argument, value)
245260end
246261247262function wasmlib.VM:i64_store()
248263 self:nextArg() -- alignment, ignored for now
249264 local offset = self:nextArg()
265265+ local value = table.remove(self.stack)
250266 local argument = table.remove(self.stack)
251251- local value = table.remove(self.stack)
267267+ trace("i64 stored "..value.." at "..(offset+argument))
252268 intutil.tole64(self.memory, offset + argument, value)
253269end
254270255271function wasmlib.VM:i32_store8()
256272 self:nextArg() -- alignment, ignored for now
257273 local offset = self:nextArg()
274274+ local value = table.remove(self.stack)
258275 local argument = table.remove(self.stack)
259259- local value = table.remove(self.stack)
276276+ trace("i32 8 stored "..value.." at "..(offset+argument))
260277 self.memory[offset + argument] = value & 0xFF
261278end
262279263280function wasmlib.VM:i32_store16()
264281 self:nextArg() -- alignment, ignored for now
265282 local offset = self:nextArg()
283283+ local value = table.remove(self.stack)
266284 local argument = table.remove(self.stack)
267267- local value = table.remove(self.stack)
285285+ trace("i32 16 stored "..value.." at "..(offset+argument))
268286 intutil.tole16(self.memory, offset + argument, value)
269287end
270288271289function wasmlib.VM:i64_store8()
272290 self:nextArg() -- alignment, ignored for now
273291 local offset = self:nextArg()
292292+ local value = table.remove(self.stack)
274293 local argument = table.remove(self.stack)
275275- local value = table.remove(self.stack)
294294+ trace("i64 8 stored "..value.." at "..(offset+argument))
276295 self.memory[offset + argument] = value & 0xFF
277296end
278297279298function wasmlib.VM:i64_store16()
280299 self:nextArg() -- alignment, ignored for now
281300 local offset = self:nextArg()
301301+ local value = table.remove(self.stack)
282302 local argument = table.remove(self.stack)
283283- local value = table.remove(self.stack)
303303+ trace("i64 16 stored "..value.." at "..(offset+argument))
284304 intutil.tole16(self.memory, offset + argument, value)
285305end
286306287307function wasmlib.VM:i64_store32()
288308 self:nextArg() -- alignment, ignored for now
289309 local offset = self:nextArg()
290290- local argument = table.remove(self.stack)
291310 local value = table.remove(self.stack)
311311+ local argument = table.remove(self.stack)
312312+ trace("i64 32 stored "..value.." at "..(offset+argument))
292313 intutil.tole32(self.memory, offset + argument, value)
293314end
294315···303324function wasmlib.VM:invoke(funcIndex)
304325 local f = self.functions[funcIndex]
305326 local sig = self.types[f.typeidx]
327327+ trace(funcIndex, f.typeidx, table.unpack(sig.arguments))
328328+ trace(sig.ret)
306329307330 if f.import ~= nil then
308331 local args = {}
···349372350373function wasmlib.VM:block()
351374 local curFrame = self:curFrame()
352352- local startIdx = curFrame.pc - 1 -- pc has already been incremented in step
375375+ local startIdx = curFrame.pc
353376 self:nextArg() -- block result type, ignored for now
354377 local endIdx = findMatchingEndOrElse(self:curBody(), startIdx)
355355- table.insert(self.labelStack, endIdx)
378378+ table.insert(curFrame.labelStack, endIdx + 1)
356379end
357380358381function wasmlib.VM:loop()
359382 local curFrame = self:curFrame()
360360- local startIdx = curFrame.pc - 1 -- pc has already been incremented in step
383383+ local startIdx = curFrame.pc
361384 self:nextArg() -- block result type, ignored for now
362362- table.insert(self.labelStack, startIdx)
385385+ table.insert(curFrame.labelStack, startIdx)
363386end
364387365388function wasmlib.VM:_if()
389389+ local curFrame = self:curFrame()
390390+ local pc = curFrame.pc
391391+366392 self:nextArg() -- block result type, ignored for now
367393 local c = table.remove(self.stack)
368368- local curFrame = self:curFrame()
369394 local body = self.functions[curFrame.funcIndex].body
370370- local endOrElse = findMatchingEndOrElse(body, curFrame.pc - 1) -- pc has already been incremented in step
395395+ local endOrElse = findMatchingEndOrElse(body, pc)
371396372397 if body[endOrElse] == constants.opcodes.OP_ELSE then
373398 local elseIdx = endOrElse
374399 local endIdx = findMatchingEndOrElse(body, endOrElse)
375400 if c == 0 then
376376- curFrame.pc = elseIdx
401401+ curFrame.pc = elseIdx -- instruction after ELSE
377402 end
378378- table.insert(self.labelStack, endIdx)
403403+ table.insert(curFrame.labelStack, endIdx + 1)
379404 else
380405 local endIdx = endOrElse
381406 if c == 0 then
382382- curFrame.pc = endIdx + 1
407407+ curFrame.pc = endIdx -- instruction after END
383408 else
384384- table.insert(self.labelStack, endIdx)
409409+ table.insert(curFrame.labelStack, endIdx + 1)
385410 end
386411 end
387412end
388413414414+function wasmlib.VM:_else()
415415+ -- jump to label on top of stack
416416+ local curFrame = self:curFrame()
417417+ local label = table.remove(curFrame.labelStack)
418418+ self:curFrame().pc = label - 1
419419+end
420420+389421function wasmlib.VM:brInner(labelIdx)
390390- local label = self.labelStack[#self.labelStack - labelIdx]
422422+ local curFrame = self:curFrame()
423423+ local label = curFrame.labelStack[#curFrame.labelStack - labelIdx]
391424 for _ = 1, labelIdx + 1 do
392392- table.remove(self.labelStack)
425425+ table.remove(curFrame.labelStack)
393426 end
394394- self:curFrame().pc = label
427427+ self:curFrame().pc = label - 1
395428end
396429397430function wasmlib.VM:br()
···408441end
409442410443function wasmlib.VM:br_table()
411411- local table = self:nextArg()
444444+ local tab = self:nextArg()
412445 local other = self:nextArg()
413446 local i = table.remove(self.stack)
414447415448 if i < #table then
416416- self:brInner(table[i + 1])
449449+ self:brInner(tab[i + 1])
417450 else
418451 self:brInner(other)
419452 end
420453end
421454455455+function wasmlib.VM:_end()
456456+ local curFrame = self:curFrame()
457457+ table.remove(curFrame.labelStack)
458458+end
459459+422460function wasmlib.VM:step()
423461 if self:curFrame().pc >= #self:curBody() then
462462+ trace("returning", self:curFrame().pc, #self:curBody())
424463 self:ret()
425464 return
426465 end
427466428467 local opcode = self:nextArg()
429429- trace(self:curFrame().pc,opcode,"###",table.unpack(self.stack))
430430- trace(#self.labelStack,"---",table.unpack(self.labelStack))
468468+ trace(self:curFrame().funcIndex, self:curFrame().pc,opcode, "###", table.unpack(self.stack))
469469+ trace(#self:curFrame().labelStack, "---", table.unpack(self:curFrame().labelStack))
431470432471 local c = constants.opcodes
433472 local optable = {
···437476 [c.OP_BLOCK] = function() self:block() end,
438477 [c.OP_LOOP] = function() self:loop() end,
439478 [c.OP_IF] = function() self:_if() end,
440440- [c.OP_ELSE] = function() table.remove(self.labelStack) end,
441441- [c.OP_END] = function() table.remove(self.labelStack) end,
479479+ [c.OP_ELSE] = function() self:_else() end,
480480+ [c.OP_END] = function() self:_end() end,
442481 [c.OP_BR] = function() self:br() end,
443482 [c.OP_BR_IF] = function() self:br_if() end,
444483 [c.OP_BR_TABLE] = function() self:br_table() end,
445484 [c.OP_RETURN] = function() self:ret() end,
446485 [c.OP_CALL] = function() self:call() end,
447447- -- CALL_INDIRECT
486486+ [c.OP_CALL_INDIRECT] = function() self:call_indirect() end,
448487 -- parametric
449488 [c.OP_DROP] = function() table.remove(self.stack) end,
450489 [c.OP_SELECT] = function() self:triop(ops.select) end,
···492531 [c.OP_I32_GT_U] = function() self:binop(ops.i32_gt_u) end,
493532 [c.OP_I32_LE_S] = function() self:binop(ops.i32_le_s) end,
494533 [c.OP_I32_LE_U] = function() self:binop(ops.i32_le_u) end,
534534+ [c.OP_I32_GE_S] = function() self:binop(ops.i32_ge_s) end,
535535+ [c.OP_I32_GE_U] = function() self:binop(ops.i32_ge_u) end,
495536 -- i64 comparisons
496537 [c.OP_I64_EQZ] = function() self:unop (ops.i64_eqz) end,
497538 [c.OP_I64_EQ] = function() self:binop(ops.i64_eq) end,
···539580 [c.OP_I64_OR] = function() self:binop(ops.i64_or) end,
540581 [c.OP_I64_XOR] = function() self:binop(ops.i64_xor) end,
541582 [c.OP_I64_SHL] = function() self:binop(ops.i64_shl) end,
542542- [c.OP_I64_SHR_S] = function() self:binop(ops.i64_shr_s) end,
543543- -- I64_SHR_U
583583+ -- I64_SHR_S
584584+ [c.OP_I64_SHR_U] = function() self:binop(ops.i64_shr_u) end,
544585 [c.OP_I64_ROTL] = function() self:binop(ops.i64_rotl) end,
545586 [c.OP_I64_ROTR] = function() self:binop(ops.i64_rotr) end,
546587 -- [float operations]
547588 -- conversions
548548- [c.OP_I32_WRAP_I64] = function() self:unop(ops.i32_wrap_i64) end,
589589+ [c.OP_I32_WRAP_I64] = function() self:unop (ops.i32_wrap_i64) end,
549590 -- [float stuff]
550550- [c.OP_I64_EXTEND_I32_S] = function() self:unop(ops.i64_extend_i32_s) end,
551551- [c.OP_I64_EXTEND_I32_U] = function() self:unop(ops.i64_extend_i32_u) end,
591591+ [c.OP_I64_EXTEND_I32_S] = function() self:unop (ops.i64_extend_i32_s) end,
592592+ [c.OP_I64_EXTEND_I32_U] = function() self:unop (ops.i64_extend_i32_u) end,
552593 -- [float stuff]
594594+ -- sign ext
595595+ [c.OP_I32_EXTEND8_S] = function() self:unop (ops.i32_extend8_s) end,
596596+ [c.OP_I32_EXTEND16_S] = function() self:unop (ops.i32_extend16_s) end,
597597+ [c.OP_I64_EXTEND8_S] = function() self:unop (ops.i64_extend8_s) end,
598598+ [c.OP_I64_EXTEND16_S] = function() self:unop (ops.i64_extend16_s) end,
599599+ [c.OP_I64_EXTEND32_S] = function() self:unop (ops.i64_extend32_s) end,
553600 }
554601555602 local opfunc = optable[opcode]
···627674end
628675629676function wasmlib.VM:parseImports(bytes, idx, imports)
677677+ trace("parsing imports section")
630678 local szlen, _ = intutil.fromuleb128(bytes, idx)
631679 idx = idx + szlen
632680 local nilen, numImports = intutil.fromuleb128(bytes, idx)
···668716end
669717670718function wasmlib.VM:parseFunctions(bytes, idx)
719719+ trace("parsing functions section")
671720 local szlen, _ = intutil.fromuleb128(bytes, idx)
672721 idx = idx + szlen
673722 local nflen, numFuncs = intutil.fromuleb128(bytes, idx)
···682731 return idx
683732end
684733685685-function wasmlib.VM:parseTables(bytes, idx, imports) -- luacheck: no unused args
686686- print("warning: skipping tables section")
734734+function wasmlib.VM:parseTables(bytes, idx) -- luacheck: no unused args
735735+ -- FIXME: we just assume there is always a table, and don't check the size/types at all
687736 local szlen, size = intutil.fromuleb128(bytes, idx)
688737 return idx + szlen + size
689738end
690739691740function wasmlib.VM:parseMemory(bytes, idx)
741741+ trace("parsing memory section")
692742 local szlen, _ = intutil.fromuleb128(bytes, idx)
693743 idx = idx + szlen
694744 local nmlen, numMems = intutil.fromuleb128(bytes, idx)
···702752703753 local minlen, min = intutil.fromuleb128(bytes, idx)
704754 idx = idx + minlen
705705- self.memory = memory.new(min)
755755+ self.memory = memory.Memory:new(min)
706756707757 if limitFlag == 1 then
708758 local maxlen, max = intutil.fromuleb128(bytes, idx)
···741791end
742792743793function wasmlib.VM:parseGlobals(bytes, idx)
794794+ trace("parsing globals section")
744795 local szlen, _ = intutil.fromuleb128(bytes, idx)
745796 idx = idx + szlen
746797 local nglen, numGlobs = intutil.fromuleb128(bytes, idx)
···757808 return idx
758809end
759810760760-function wasmlib.VM:parseExports(bytes, idx) -- luacheck: no unused args
761761- print("warning: skipping exports section")
762762- local szlen, size = intutil.fromuleb128(bytes, idx)
763763- return idx + szlen + size
811811+function wasmlib.VM:parseExports(bytes, idx)
812812+ trace("parsing exports section")
813813+ local szlen, _ = intutil.fromuleb128(bytes, idx)
814814+ idx = idx + szlen
815815+ local nelen, numExports = intutil.fromuleb128(bytes, idx)
816816+ idx = idx + nelen
817817+818818+ for _ = 1, numExports do
819819+ local nllen, nameLen = intutil.fromuleb128(bytes, idx)
820820+ idx = idx + nllen
821821+ local exportName = strutil.bytestostr(bytes, idx, nameLen)
822822+ idx = idx + nameLen
823823+824824+ local exportDesc = bytes[idx]
825825+ idx = idx + 1
826826+ if exportDesc == 0x00 then
827827+ local funcIdx = bytes[idx] + 1
828828+ idx = idx + 1
829829+830830+ self.exports[exportName] = function(...)
831831+ trace("called export "..exportName)
832832+ local args = {...}
833833+ local nargs = #self.types[self.functions[funcIdx].typeidx].arguments
834834+ if #args ~= nargs then
835835+ error("exported function "..exportName.." called with incorrect number of arguments")
836836+ end
837837+838838+ for i = 1, nargs do
839839+ table.insert(self.stack, args[i])
840840+ end
841841+ self:invoke(funcIdx)
842842+ while #self.stackFrames > 0 do
843843+ self:step()
844844+ end
845845+846846+ if self.types[self.functions[funcIdx].typeidx].ret ~= nil then
847847+ return table.remove(self.stack)
848848+ end
849849+ end
850850+ elseif exportDesc == 0x01 then
851851+ idx = idx + 1
852852+ print("warning: ignoring table export")
853853+ elseif exportDesc == 0x02 then
854854+ idx = idx + 1
855855+ print("warning: ignoring memory export")
856856+ elseif exportDesc == 0x03 then
857857+ idx = idx + 1
858858+ print("warning: ignoring global export")
859859+ else
860860+ error("invalid export type "..exportDesc)
861861+ end
862862+ end
863863+864864+ return idx
764865end
765866766867function wasmlib.VM:parseStart(bytes, idx) -- luacheck: no unused args
···769870 return idx + szlen + size
770871end
771872772772-function wasmlib.VM:parseElements(bytes, idx) -- luacheck: no unused args
773773- print("warning: skipping elements section")
774774- local szlen, size = intutil.fromuleb128(bytes, idx)
775775- return idx + szlen + size
873873+function wasmlib.VM:parseElements(bytes, idx)
874874+ local szlen, _ = intutil.fromuleb128(bytes, idx)
875875+ idx = idx + szlen
876876+ local nelen, numElems = intutil.fromuleb128(bytes, idx)
877877+ idx = idx + nelen
878878+879879+ for _ = 1, numElems do
880880+ local tilen, tabIdx = intutil.fromuleb128(bytes, idx)
881881+ idx = idx + tilen
882882+ if tabIdx ~= 0 then
883883+ error("tableidx must be zero")
884884+ end
885885+886886+ local nidx, offset = parseConstexpr(bytes, idx)
887887+ idx = nidx
888888+889889+ local nflen, numFunctions = intutil.fromuleb128(bytes, idx)
890890+ idx = idx + nflen
891891+ for i = 0, numFunctions - 1 do
892892+ local filen, funcIdx = intutil.fromuleb128(bytes, idx)
893893+ idx = idx + filen
894894+ self.table[offset+i] = funcIdx + 1
895895+ end
896896+ end
897897+898898+ return idx
776899end
777900778901function wasmlib.VM:parseCode(bytes, idx)
902902+ trace("parsing code section")
779903 local szlen, _ = intutil.fromuleb128(bytes, idx)
780904 idx = idx + szlen
781905 local nclen, numCode = intutil.fromuleb128(bytes, idx)
···845969 idx = idx + alen
846970 table.insert(body, a)
847971 elseif operand:sub(1,1) == "V" then
972972+ local v = {}
848973 local vecType = operand:sub(2,2)
849974 if vecType ~= "u" then
850975 error("unimplemented")
···856981 for _ = 1, vecLen do
857982 local alen, a = intutil.fromuleb128(bytes, idx)
858983 idx = idx + alen
859859- table.insert(body, a)
984984+ table.insert(v, a)
860985 end
986986+987987+ table.insert(body, v)
861988 end
862989 end
863990 until nestDepth == -1 -- expr is terminated with an END opcode which isn't part of any control flow structure,
864991 -- therefore the nestDepth should end up at -1
992992+ body[#body] = nil -- remove the END terminator
865993 self.functions[i].body = body
866994 end
867995···869997end
870998871999function wasmlib.VM:parseData(bytes, idx)
10001000+ trace("parsing data section")
8721001 local szlen, _ = intutil.fromuleb128(bytes, idx)
8731002 idx = idx + szlen
8741003 local ndlen, numData = intutil.fromuleb128(bytes, idx)