···88wasmlib.VM = {
99 stack = {},
1010 stackFrames = {},
1111+ labelStack = {},
1112 functions = {},
1213 types = {},
1314 memory = {},
···4344end
44454546function wasmlib.VM:readarg8()
4646- local curFrame = self.topFrame()
4747+ local curFrame = self:topFrame()
4748 local body = self.functions[curFrame.funcIndex].body
4849 local result = body[curFrame.pc]
4950 curFrame.pc = curFrame.pc + 1
···132133function wasmlib.VM:i32_load()
133134 self:readarg32() -- alignment, ignored for now
134135 local offset = self:readarg32()
135135- local value = intutil.fromle32(self.memory, offset)
136136+ local argument = table.remove(self.stack)
137137+ local value = intutil.fromle32(self.memory, offset + argument)
136138 table.insert(self.stack, value)
137139end
138140139141function wasmlib.VM:i64_load()
140142 self:readarg32() -- alignment, ignored for now
141143 local offset = self:readarg32()
142142- local value = intutil.fromle64(self.memory, offset)
144144+ local argument = table.remove(self.stack)
145145+ local value = intutil.fromle64(self.memory, offset + argument)
143146 table.insert(self.stack, value)
144147end
145148146149function wasmlib.VM:i32_load8_s()
147150 self:readarg32() -- alignment, ignored for now
148151 local offset = self:readarg32()
149149- local value = intutil.signexti8(self.memory[offset]) & constants.I32_MAX
152152+ local argument = table.remove(self.stack)
153153+ local value = intutil.signexti8(self.memory[offset + argument]) & constants.I32_MAX
150154 table.insert(self.stack, value)
151155end
152156153157function wasmlib.VM:i32_load8_u()
154158 self:readarg32() -- alignment, ignored for now
155159 local offset = self:readarg32()
156156- local value = self.memory[offset]
160160+ local argument = table.remove(self.stack)
161161+ local value = self.memory[offset + argument]
157162 table.insert(self.stack, value)
158163end
159164160165function wasmlib.VM:i32_load16_s()
161166 self:readarg32() -- alignment, ignored for now
162167 local offset = self:readarg32()
163163- local value = intutil.signexti16(intutil.fromle16(self.memory, offset)) & constants.I32_MAX
168168+ local argument = table.remove(self.stack)
169169+ local value = intutil.signexti16(intutil.fromle16(self.memory, offset + argument)) & constants.I32_MAX
164170 table.insert(self.stack, value)
165171end
166172167173function wasmlib.VM:i32_load16_u()
168174 self:readarg32() -- alignment, ignored for now
169175 local offset = self:readarg32()
170170- local value = intutil.fromle16(self.memory, offset)
176176+ local argument = table.remove(self.stack)
177177+ local value = intutil.fromle16(self.memory, offset + argument)
171178 table.insert(self.stack, value)
172179end
173180174181function wasmlib.VM:i64_load8_s()
175182 self:readarg32() -- alignment, ignored for now
176183 local offset = self:readarg32()
177177- local value = intutil.signexti8(self.memory[offset])
184184+ local argument = table.remove(self.stack)
185185+ local value = intutil.signexti8(self.memory[offset + argument])
178186 table.insert(self.stack, value)
179187end
180188181189function wasmlib.VM:i64_load8_u()
182190 self:readarg32() -- alignment, ignored for now
183191 local offset = self:readarg32()
184184- local value = self.memory[offset]
192192+ local argument = table.remove(self.stack)
193193+ local value = self.memory[offset + argument]
185194 table.insert(self.stack, value)
186195end
187196188197function wasmlib.VM:i64_load16_s()
189198 self:readarg32() -- alignment, ignored for now
190199 local offset = self:readarg32()
191191- local value = intutil.signexti16(intutil.fromle16(self.memory, offset))
200200+ local argument = table.remove(self.stack)
201201+ local value = intutil.signexti16(intutil.fromle16(self.memory, offset + argument))
192202 table.insert(self.stack, value)
193203end
194204195205function wasmlib.VM:i64_load16_u()
196206 self:readarg32() -- alignment, ignored for now
197207 local offset = self:readarg32()
198198- local value = intutil.fromle16(self.memory, offset)
208208+ local argument = table.remove(self.stack)
209209+ local value = intutil.fromle16(self.memory, offset + argument)
199210 table.insert(self.stack, value)
200211end
201212202213function wasmlib.VM:i64_load32_s()
203214 self:readarg32() -- alignment, ignored for now
204215 local offset = self:readarg32()
205205- local value = intutil.signexti32(intutil.fromle32(self.memory, offset))
216216+ local argument = table.remove(self.stack)
217217+ local value = intutil.signexti32(intutil.fromle32(self.memory, offset + argument))
206218 table.insert(self.stack, value)
207219end
208220209221function wasmlib.VM:i64_load32_u()
210222 self:readarg32() -- alignment, ignored for now
211223 local offset = self:readarg32()
212212- local value = intutil.fromle32(self.memory, offset)
224224+ local argument = table.remove(self.stack)
225225+ local value = intutil.fromle32(self.memory, offset + argument)
213226 table.insert(self.stack, value)
214227end
215228216229function wasmlib.VM:i64_load()
217230 self:readarg32() -- alignment, ignored for now
218231 local offset = self:readarg32()
219219- local value = intutil.signexti16(intutil.fromle16(self.memory, offset))
232232+ local argument = table.remove(self.stack)
233233+ local value = intutil.signexti16(intutil.fromle16(self.memory, offset + argument))
220234 table.insert(self.stack, value)
221235end
222236223237function wasmlib.VM:i32_store()
224238 self:readarg32() -- alignment, ignored for now
225239 local offset = self:readarg32()
240240+ local argument = table.remove(self.stack)
226241 local value = table.remove(self.stack)
227227- intutil.tole32(self.memory, offset, value)
242242+ intutil.tole32(self.memory, offset + argument, value)
228243end
229244230245function wasmlib.VM:i64_store()
231246 self:readarg32() -- alignment, ignored for now
232247 local offset = self:readarg32()
248248+ local argument = table.remove(self.stack)
233249 local value = table.remove(self.stack)
234234- intutil.tole64(self.memory, offset, value)
250250+ intutil.tole64(self.memory, offset + argument, value)
235251end
236252237253function wasmlib.VM:i32_store8()
238254 self:readarg32() -- alignment, ignored for now
239255 local offset = self:readarg32()
256256+ local argument = table.remove(self.stack)
240257 local value = table.remove(self.stack)
241241- self.memory[offset] = value & 0xFF
258258+ self.memory[offset + argument] = value & 0xFF
242259end
243260244261function wasmlib.VM:i32_store16()
245262 self:readarg32() -- alignment, ignored for now
246263 local offset = self:readarg32()
264264+ local argument = table.remove(self.stack)
247265 local value = table.remove(self.stack)
248248- intutil.tole16(self.memory, offset, value)
266266+ intutil.tole16(self.memory, offset + argument, value)
249267end
250268251269function wasmlib.VM:i64_store8()
252270 self:readarg32() -- alignment, ignored for now
253271 local offset = self:readarg32()
272272+ local argument = table.remove(self.stack)
254273 local value = table.remove(self.stack)
255255- self.memory[offset] = value & 0xFF
274274+ self.memory[offset + argument] = value & 0xFF
256275end
257276258277function wasmlib.VM:i64_store16()
259278 self:readarg32() -- alignment, ignored for now
260279 local offset = self:readarg32()
280280+ local argument = table.remove(self.stack)
261281 local value = table.remove(self.stack)
262262- intutil.tole16(self.memory, offset, value)
282282+ intutil.tole16(self.memory, offset + argument, value)
263283end
264284265285function wasmlib.VM:i64_store32()
266286 self:readarg32() -- alignment, ignored for now
267287 local offset = self:readarg32()
288288+ local argument = table.remove(self.stack)
268289 local value = table.remove(self.stack)
269269- intutil.tole32(self.memory, offset, value)
290290+ intutil.tole32(self.memory, offset + argument, value)
270291end
271292272293function wasmlib.VM:i32_const()
···281302 local fr = frame.StackFrame:new(funcIndex)
282303 local f = self.functions[funcIndex]
283304 local sig = self.types[f.typeidx]
284284- for i = 1, #sig.arguments do
285285- fr.locals[#sig.arguments - i] = table.remove(self.stack)
305305+306306+ -- NOTE: sig.arguments is zero-indexed, so #sig.arguments is one less than the real length
307307+ if f.import ~= nil then
308308+ local args = {}
309309+ for i = 1, #sig.arguments + 1 do
310310+ args[#sig.arguments + 2 - i] = table.remove(self.stack)
311311+ end
312312+ local ret = f.import(table.unpack(args))
313313+ if sig.ret ~= nil then
314314+ table.insert(self.stack, ret)
315315+ end
316316+ return
317317+ end
318318+319319+ for i = 1, #sig.arguments + 1 do
320320+ fr.locals[#sig.arguments + 1 - i] = table.remove(self.stack)
286321 end
287322 table.insert(self.stackFrames, fr)
288323end
···291326 table.remove(self.stackFrames)
292327end
293328329329+-- Get the index of the next occurence of the instruction with opcode `target`
330330+-- starting from `i` at the same level of nesting
331331+function wasmlib.VM:findMatchingEndOrElse(i, depth)
332332+ depth = depth or 0
333333+ local curFrame = self:topFrame()
334334+ local body = self.functions[curFrame.funcIndex].body
335335+ repeat
336336+ local opcode = body[i]
337337+ local length = constants.ilengths[opcode]
338338+ if length == 0 then
339339+ if (opcode == constants.opcodes.OP_BLOCK)
340340+ or (opcode == constants.opcodes.OP_LOOP)
341341+ or (opcode == constants.opcodes.OP_IF)
342342+ then
343343+ i = self:findMatchingEndOrElse(i + 1, depth + 1) + (depth > 0 and 1 or 0)
344344+ elseif opcode == constants.opcodes.OP_ELSE then
345345+ i = i + 1
346346+ elseif opcode == constants.opcodes.OP_BR_TABLE then
347347+ local vecLen = intutil.fromle32(body, i + 1)
348348+ i = i + (1 + 4 * (vecLen + 1)) -- 1 byte opcode, (vecLen + 1) 4-byte label indices
349349+ end
350350+ else
351351+ i = i + length
352352+ end
353353+ until (body[i] == constants.opcodes.OP_END) or (depth <= 1 and body[i] == constants.opcodes.OP_ELSE)
354354+ return i
355355+end
356356+357357+function wasmlib.VM:block()
358358+ local curFrame = self:topFrame()
359359+ local startIdx = curFrame.pc - 1 -- pc has already been incremented in step
360360+ self:readarg8() -- block result type, ignored for now
361361+ local endIdx = self:findMatchingEndOrElse(startIdx)
362362+ table.insert(self.labelStack, endIdx)
363363+end
364364+365365+function wasmlib.VM:loop()
366366+ local curFrame = self:topFrame()
367367+ local startIdx = curFrame.pc - 1 -- pc has already been incremented in step
368368+ self:readarg8() -- block result type, ignored for now
369369+ table.insert(self.labelStack, startIdx)
370370+end
371371+372372+function wasmlib.VM:_if()
373373+ self:readarg8() -- block result type, ignored for now
374374+ local c = table.remove(self.stack)
375375+ local curFrame = self:topFrame()
376376+ local body = self.functions[curFrame.funcIndex].body
377377+ local endOrElse = self:findMatchingEndOrElse(curFrame.pc - 1) -- pc has already been incremented in step
378378+379379+ if body[endOrElse] == constants.opcodes.OP_ELSE then
380380+ local elseIdx = endOrElse
381381+ local endIdx = self:findMatchingEndOrElse(endOrElse)
382382+ if c == 0 then
383383+ curFrame.pc = elseIdx
384384+ end
385385+ table.insert(self.labelStack, endIdx)
386386+ else
387387+ local endIdx = endOrElse
388388+ if c == 0 then
389389+ curFrame.pc = endIdx + 1
390390+ else
391391+ table.insert(self.labelStack, endIdx)
392392+ end
393393+ end
394394+end
395395+396396+function wasmlib.VM:brInner(labelIdx)
397397+ local label = self.labelStack[#self.labelStack - labelIdx]
398398+ for _ = 1, labelIdx + 1 do
399399+ table.remove(self.labelStack)
400400+ end
401401+ self:topFrame().pc = label
402402+end
403403+404404+function wasmlib.VM:br()
405405+ local labelIdx = self:readarg32()
406406+ self:brInner(labelIdx)
407407+end
408408+409409+function wasmlib.VM:br_if()
410410+ local labelIdx = self:readarg32()
411411+ local c = table.remove(self.stack)
412412+ if c ~= 0 then
413413+ self:brInner(labelIdx)
414414+ end
415415+end
416416+417417+function wasmlib.VM:br_table()
418418+ local curFrame = self:topFrame()
419419+ local body = self.functions[curFrame.funcIndex].body
420420+ local vLen = self:readarg32()
421421+ local i = table.remove(self.stack)
422422+423423+ if i < vLen then
424424+ local labelIdx = intutil.fromle32(body, curFrame.pc + i * 4)
425425+ self:brInner(labelIdx)
426426+ else
427427+ local labelIdx = intutil.fromle32(body, curFrame.pc + vLen * 4)
428428+ self:brInner(labelIdx)
429429+ end
430430+end
431431+294432function wasmlib.VM:step()
295433 local curFrame = self:topFrame()
296434 local body = self.functions[curFrame.funcIndex].body
···302440 -- control
303441 [c.OP_UNREACHABLE] = function() error("unreachable") end,
304442 [c.OP_NOP] = function() end,
305305- -- BLOCK
306306- -- LOOP
307307- -- IF
308308- -- ELSE
309309- -- END
310310- -- BR
311311- -- BR_IF
312312- -- BR_TABLE
443443+ [c.OP_BLOCK] = function() self:block() end,
444444+ [c.OP_LOOP] = function() self:loop() end,
445445+ [c.OP_IF] = function() self:_if() end,
446446+ [c.OP_ELSE] = function() table.remove(self.labelStack) end,
447447+ [c.OP_END] = function() table.remove(self.labelStack) end,
448448+ [c.OP_BR] = function() self:br() end,
449449+ [c.OP_BR_IF] = function() self:br_if() end,
450450+ [c.OP_BR_TABLE] = function() self:br_table() end,
313451 [c.OP_RETURN] = function() self:ret() end,
314452 [c.OP_CALL] = function() self:call() end,
315453 -- CALL_INDIRECT
···338476 [c.OP_I64_LOAD32_U] = function() self:i64_load32_u() end,
339477 [c.OP_I32_STORE] = function() self:i32_store() end,
340478 [c.OP_I64_STORE] = function() self:i64_store() end,
341341- -- [floart instrs]
479479+ -- [float instrs]
342480 [c.OP_I32_STORE8] = function() self:i32_store8() end,
343481 [c.OP_I32_STORE16] = function() self:i32_store16() end,
344482 [c.OP_I64_STORE8] = function() self:i64_store8() end,