1package interpreter
2
3import (
4 "bytes"
5 "encoding/binary"
6 "fmt"
7 "math"
8 "strings"
9
10 "github.com/tetratelabs/wazero/api"
11 "github.com/tetratelabs/wazero/internal/leb128"
12 "github.com/tetratelabs/wazero/internal/wasm"
13)
14
15type controlFrameKind byte
16
17const (
18 controlFrameKindBlockWithContinuationLabel controlFrameKind = iota
19 controlFrameKindBlockWithoutContinuationLabel
20 controlFrameKindFunction
21 controlFrameKindLoop
22 controlFrameKindIfWithElse
23 controlFrameKindIfWithoutElse
24)
25
26type (
27 controlFrame struct {
28 frameID uint32
29 // originalStackLenWithoutParam holds the number of values on the stack
30 // when Start executing this control frame minus params for the block.
31 originalStackLenWithoutParam int
32 // originalStackLenWithoutParamUint64 is almost the same as originalStackLenWithoutParam
33 // except that it holds the number of values on the stack in uint64.
34 originalStackLenWithoutParamUint64 int
35 blockType *wasm.FunctionType
36 kind controlFrameKind
37 }
38 controlFrames struct{ frames []controlFrame }
39)
40
41func (c *controlFrame) ensureContinuation() {
42 // Make sure that if the frame is block and doesn't have continuation,
43 // change the Kind so we can emit the continuation block
44 // later when we reach the End instruction of this frame.
45 if c.kind == controlFrameKindBlockWithoutContinuationLabel {
46 c.kind = controlFrameKindBlockWithContinuationLabel
47 }
48}
49
50func (c *controlFrame) asLabel() label {
51 switch c.kind {
52 case controlFrameKindBlockWithContinuationLabel,
53 controlFrameKindBlockWithoutContinuationLabel:
54 return newLabel(labelKindContinuation, c.frameID)
55 case controlFrameKindLoop:
56 return newLabel(labelKindHeader, c.frameID)
57 case controlFrameKindFunction:
58 return newLabel(labelKindReturn, 0)
59 case controlFrameKindIfWithElse,
60 controlFrameKindIfWithoutElse:
61 return newLabel(labelKindContinuation, c.frameID)
62 }
63 panic(fmt.Sprintf("unreachable: a bug in interpreterir implementation: %v", c.kind))
64}
65
66func (c *controlFrames) functionFrame() *controlFrame {
67 // No need to check stack bound
68 // as we can assume that all the operations
69 // are valid thanks to validateFunction
70 // at module validation phase.
71 return &c.frames[0]
72}
73
74func (c *controlFrames) get(n int) *controlFrame {
75 // No need to check stack bound
76 // as we can assume that all the operations
77 // are valid thanks to validateFunction
78 // at module validation phase.
79 return &c.frames[len(c.frames)-n-1]
80}
81
82func (c *controlFrames) top() *controlFrame {
83 // No need to check stack bound
84 // as we can assume that all the operations
85 // are valid thanks to validateFunction
86 // at module validation phase.
87 return &c.frames[len(c.frames)-1]
88}
89
90func (c *controlFrames) empty() bool {
91 return len(c.frames) == 0
92}
93
94func (c *controlFrames) pop() (frame *controlFrame) {
95 // No need to check stack bound
96 // as we can assume that all the operations
97 // are valid thanks to validateFunction
98 // at module validation phase.
99 frame = c.top()
100 c.frames = c.frames[:len(c.frames)-1]
101 return
102}
103
104func (c *controlFrames) push(frame controlFrame) {
105 c.frames = append(c.frames, frame)
106}
107
108func (c *compiler) initializeStack() {
109 // Reuse the existing slice.
110 c.localIndexToStackHeightInUint64 = c.localIndexToStackHeightInUint64[:0]
111 var current int
112 for _, lt := range c.sig.Params {
113 c.localIndexToStackHeightInUint64 = append(c.localIndexToStackHeightInUint64, current)
114 if lt == wasm.ValueTypeV128 {
115 current++
116 }
117 current++
118 }
119
120 if c.callFrameStackSizeInUint64 > 0 {
121 // We reserve the stack slots for result values below the return call frame slots.
122 if diff := c.sig.ResultNumInUint64 - c.sig.ParamNumInUint64; diff > 0 {
123 current += diff
124 }
125 }
126
127 // Non-func param locals Start after the return call frame.
128 current += c.callFrameStackSizeInUint64
129
130 for _, lt := range c.localTypes {
131 c.localIndexToStackHeightInUint64 = append(c.localIndexToStackHeightInUint64, current)
132 if lt == wasm.ValueTypeV128 {
133 current++
134 }
135 current++
136 }
137
138 // Push function arguments.
139 for _, t := range c.sig.Params {
140 c.stackPush(wasmValueTypeTounsignedType(t))
141 }
142
143 if c.callFrameStackSizeInUint64 > 0 {
144 // Reserve the stack slots for results.
145 for i := 0; i < c.sig.ResultNumInUint64-c.sig.ParamNumInUint64; i++ {
146 c.stackPush(unsignedTypeI64)
147 }
148
149 // Reserve the stack slots for call frame.
150 for i := 0; i < c.callFrameStackSizeInUint64; i++ {
151 c.stackPush(unsignedTypeI64)
152 }
153 }
154}
155
156// compiler is in charge of lowering raw Wasm function body to get compilationResult.
157// This is created per *wasm.Module and reused for all functions in it to reduce memory allocations.
158type compiler struct {
159 module *wasm.Module
160 enabledFeatures api.CoreFeatures
161 callFrameStackSizeInUint64 int
162 stack []unsignedType
163 // stackLenInUint64 is the length of the stack in uint64.
164 stackLenInUint64 int
165 currentFrameID uint32
166 controlFrames controlFrames
167 unreachableState struct {
168 on bool
169 depth int
170 }
171 pc, currentOpPC uint64
172 result compilationResult
173
174 // body holds the code for the function's body where Wasm instructions are stored.
175 body []byte
176 // sig is the function type of the target function.
177 sig *wasm.FunctionType
178 // localTypes holds the target function locals' value types except function params.
179 localTypes []wasm.ValueType
180 // localIndexToStackHeightInUint64 maps the local index (starting with function params) to the stack height
181 // where the local is places. This is the necessary mapping for functions who contain vector type locals.
182 localIndexToStackHeightInUint64 []int
183
184 // types hold all the function types in the module where the targe function exists.
185 types []wasm.FunctionType
186 // funcs holds the type indexes for all declared functions in the module where the target function exists.
187 funcs []uint32
188 // globals holds the global types for all declared globals in the module where the target function exists.
189 globals []wasm.GlobalType
190
191 // needSourceOffset is true if this module requires DWARF based stack trace.
192 needSourceOffset bool
193 // bodyOffsetInCodeSection is the offset of the body of this function in the original Wasm binary's code section.
194 bodyOffsetInCodeSection uint64
195
196 ensureTermination bool
197 // Pre-allocated bytes.Reader to be used in various places.
198 br *bytes.Reader
199 funcTypeToSigs funcTypeToIRSignatures
200
201 next int
202}
203
204//lint:ignore U1000 for debugging only.
205func (c *compiler) stackDump() string {
206 strs := make([]string, 0, len(c.stack))
207 for _, s := range c.stack {
208 strs = append(strs, s.String())
209 }
210 return "[" + strings.Join(strs, ", ") + "]"
211}
212
213func (c *compiler) markUnreachable() {
214 c.unreachableState.on = true
215}
216
217func (c *compiler) resetUnreachable() {
218 c.unreachableState.on = false
219}
220
221// memoryType is the type of memory in a compiled module.
222type memoryType byte
223
224const (
225 // memoryTypeNone indicates there is no memory.
226 memoryTypeNone memoryType = iota
227 // memoryTypeStandard indicates there is a non-shared memory.
228 memoryTypeStandard
229 // memoryTypeShared indicates there is a shared memory.
230 memoryTypeShared
231)
232
233type compilationResult struct {
234 // Operations holds interpreterir operations compiled from Wasm instructions in a Wasm function.
235 Operations []unionOperation
236
237 // IROperationSourceOffsetsInWasmBinary is index-correlated with Operation and maps each operation to the corresponding source instruction's
238 // offset in the original WebAssembly binary.
239 // Non nil only when the given Wasm module has the DWARF section.
240 IROperationSourceOffsetsInWasmBinary []uint64
241
242 // LabelCallers maps label to the number of callers to that label.
243 // Here "callers" means that the call-sites which jumps to the label with br, br_if or br_table
244 // instructions.
245 //
246 // Note: zero possible and allowed in wasm. e.g.
247 //
248 // (block
249 // (br 0)
250 // (block i32.const 1111)
251 // )
252 //
253 // This example the label corresponding to `(block i32.const 1111)` is never be reached at runtime because `br 0` exits the function before we reach there
254 LabelCallers map[label]uint32
255 // UsesMemory is true if this function might use memory.
256 UsesMemory bool
257
258 // The following fields are per-module values, not per-function.
259
260 // Globals holds all the declarations of globals in the module from which this function is compiled.
261 Globals []wasm.GlobalType
262 // Functions holds all the declarations of function in the module from which this function is compiled, including itself.
263 Functions []wasm.Index
264 // Types holds all the types in the module from which this function is compiled.
265 Types []wasm.FunctionType
266 // Memory indicates the type of memory of the module.
267 Memory memoryType
268 // HasTable is true if the module from which this function is compiled has table declaration.
269 HasTable bool
270 // HasDataInstances is true if the module has data instances which might be used by memory.init or data.drop instructions.
271 HasDataInstances bool
272 // HasDataInstances is true if the module has element instances which might be used by table.init or elem.drop instructions.
273 HasElementInstances bool
274}
275
276// newCompiler returns the new *compiler for the given parameters.
277// Use compiler.Next function to get compilation result per function.
278func newCompiler(enabledFeatures api.CoreFeatures, callFrameStackSizeInUint64 int, module *wasm.Module, ensureTermination bool) (*compiler, error) {
279 functions, globals, mem, tables, err := module.AllDeclarations()
280 if err != nil {
281 return nil, err
282 }
283
284 hasTable, hasDataInstances, hasElementInstances := len(tables) > 0,
285 len(module.DataSection) > 0, len(module.ElementSection) > 0
286
287 var mt memoryType
288 switch {
289 case mem == nil:
290 mt = memoryTypeNone
291 case mem.IsShared:
292 mt = memoryTypeShared
293 default:
294 mt = memoryTypeStandard
295 }
296
297 types := module.TypeSection
298
299 c := &compiler{
300 module: module,
301 enabledFeatures: enabledFeatures,
302 controlFrames: controlFrames{},
303 callFrameStackSizeInUint64: callFrameStackSizeInUint64,
304 result: compilationResult{
305 Globals: globals,
306 Functions: functions,
307 Types: types,
308 Memory: mt,
309 HasTable: hasTable,
310 HasDataInstances: hasDataInstances,
311 HasElementInstances: hasElementInstances,
312 LabelCallers: map[label]uint32{},
313 },
314 globals: globals,
315 funcs: functions,
316 types: types,
317 ensureTermination: ensureTermination,
318 br: bytes.NewReader(nil),
319 funcTypeToSigs: funcTypeToIRSignatures{
320 indirectCalls: make([]*signature, len(types)),
321 directCalls: make([]*signature, len(types)),
322 wasmTypes: types,
323 },
324 needSourceOffset: module.DWARFLines != nil,
325 }
326 return c, nil
327}
328
329// Next returns the next compilationResult for this compiler.
330func (c *compiler) Next() (*compilationResult, error) {
331 funcIndex := c.next
332 code := &c.module.CodeSection[funcIndex]
333 sig := &c.types[c.module.FunctionSection[funcIndex]]
334
335 // Reset the previous result.
336 c.result.Operations = c.result.Operations[:0]
337 c.result.IROperationSourceOffsetsInWasmBinary = c.result.IROperationSourceOffsetsInWasmBinary[:0]
338 c.result.UsesMemory = false
339 // Clears the existing entries in LabelCallers.
340 for frameID := uint32(0); frameID <= c.currentFrameID; frameID++ {
341 for k := labelKind(0); k < labelKindNum; k++ {
342 delete(c.result.LabelCallers, newLabel(k, frameID))
343 }
344 }
345 // Reset the previous states.
346 c.pc = 0
347 c.currentOpPC = 0
348 c.currentFrameID = 0
349 c.stackLenInUint64 = 0
350 c.unreachableState.on, c.unreachableState.depth = false, 0
351
352 if err := c.compile(sig, code.Body, code.LocalTypes, code.BodyOffsetInCodeSection); err != nil {
353 return nil, err
354 }
355 c.next++
356 return &c.result, nil
357}
358
359// Compile lowers given function instance into interpreterir operations
360// so that the resulting operations can be consumed by the interpreter
361// or the compiler compilation engine.
362func (c *compiler) compile(sig *wasm.FunctionType, body []byte, localTypes []wasm.ValueType, bodyOffsetInCodeSection uint64) error {
363 // Set function specific fields.
364 c.body = body
365 c.localTypes = localTypes
366 c.sig = sig
367 c.bodyOffsetInCodeSection = bodyOffsetInCodeSection
368
369 // Reuses the underlying slices.
370 c.stack = c.stack[:0]
371 c.controlFrames.frames = c.controlFrames.frames[:0]
372
373 c.initializeStack()
374
375 // Emit const expressions for locals.
376 // Note that here we don't take function arguments
377 // into account, meaning that callers must push
378 // arguments before entering into the function body.
379 for _, t := range c.localTypes {
380 c.emitDefaultValue(t)
381 }
382
383 // Insert the function control frame.
384 c.controlFrames.push(controlFrame{
385 frameID: c.nextFrameID(),
386 blockType: c.sig,
387 kind: controlFrameKindFunction,
388 })
389
390 // Now, enter the function body.
391 for !c.controlFrames.empty() && c.pc < uint64(len(c.body)) {
392 if err := c.handleInstruction(); err != nil {
393 return fmt.Errorf("handling instruction: %w", err)
394 }
395 }
396 return nil
397}
398
399// Translate the current Wasm instruction to interpreterir's operations,
400// and emit the results into c.results.
401func (c *compiler) handleInstruction() error {
402 op := c.body[c.pc]
403 c.currentOpPC = c.pc
404 if false {
405 var instName string
406 if op == wasm.OpcodeVecPrefix {
407 instName = wasm.VectorInstructionName(c.body[c.pc+1])
408 } else if op == wasm.OpcodeAtomicPrefix {
409 instName = wasm.AtomicInstructionName(c.body[c.pc+1])
410 } else if op == wasm.OpcodeMiscPrefix {
411 instName = wasm.MiscInstructionName(c.body[c.pc+1])
412 } else {
413 instName = wasm.InstructionName(op)
414 }
415 fmt.Printf("handling %s, unreachable_state(on=%v,depth=%d), stack=%v\n",
416 instName, c.unreachableState.on, c.unreachableState.depth, c.stack,
417 )
418 }
419
420 var peekValueType unsignedType
421 if len(c.stack) > 0 {
422 peekValueType = c.stackPeek()
423 }
424
425 // Modify the stack according the current instruction.
426 // Note that some instructions will read "index" in
427 // applyToStack and advance c.pc inside the function.
428 index, err := c.applyToStack(op)
429 if err != nil {
430 return fmt.Errorf("apply stack failed for %s: %w", wasm.InstructionName(op), err)
431 }
432 // Now we handle each instruction, and
433 // emit the corresponding interpreterir operations to the results.
434operatorSwitch:
435 switch op {
436 case wasm.OpcodeUnreachable:
437 c.emit(newOperationUnreachable())
438 c.markUnreachable()
439 case wasm.OpcodeNop:
440 // Nop is noop!
441 case wasm.OpcodeBlock:
442 c.br.Reset(c.body[c.pc+1:])
443 bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures)
444 if err != nil {
445 return fmt.Errorf("reading block type for block instruction: %w", err)
446 }
447 c.pc += num
448
449 if c.unreachableState.on {
450 // If it is currently in unreachable,
451 // just remove the entire block.
452 c.unreachableState.depth++
453 break operatorSwitch
454 }
455
456 // Create a new frame -- entering this block.
457 frame := controlFrame{
458 frameID: c.nextFrameID(),
459 originalStackLenWithoutParam: len(c.stack) - len(bt.Params),
460 originalStackLenWithoutParamUint64: c.stackLenInUint64 - bt.ParamNumInUint64,
461 kind: controlFrameKindBlockWithoutContinuationLabel,
462 blockType: bt,
463 }
464 c.controlFrames.push(frame)
465
466 case wasm.OpcodeLoop:
467 c.br.Reset(c.body[c.pc+1:])
468 bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures)
469 if err != nil {
470 return fmt.Errorf("reading block type for loop instruction: %w", err)
471 }
472 c.pc += num
473
474 if c.unreachableState.on {
475 // If it is currently in unreachable,
476 // just remove the entire block.
477 c.unreachableState.depth++
478 break operatorSwitch
479 }
480
481 // Create a new frame -- entering loop.
482 frame := controlFrame{
483 frameID: c.nextFrameID(),
484 originalStackLenWithoutParam: len(c.stack) - len(bt.Params),
485 originalStackLenWithoutParamUint64: c.stackLenInUint64 - bt.ParamNumInUint64,
486 kind: controlFrameKindLoop,
487 blockType: bt,
488 }
489 c.controlFrames.push(frame)
490
491 // Prep labels for inside and the continuation of this loop.
492 loopLabel := newLabel(labelKindHeader, frame.frameID)
493 c.result.LabelCallers[loopLabel]++
494
495 // Emit the branch operation to enter inside the loop.
496 c.emit(newOperationBr(loopLabel))
497 c.emit(newOperationLabel(loopLabel))
498
499 // Insert the exit code check on the loop header, which is the only necessary point in the function body
500 // to prevent infinite loop.
501 //
502 // Note that this is a little aggressive: this checks the exit code regardless the loop header is actually
503 // the loop. In other words, this checks even when no br/br_if/br_table instructions jumping to this loop
504 // exist. However, in reality, that shouldn't be an issue since such "noop" loop header will highly likely be
505 // optimized out by almost all guest language compilers which have the control flow optimization passes.
506 if c.ensureTermination {
507 c.emit(newOperationBuiltinFunctionCheckExitCode())
508 }
509 case wasm.OpcodeIf:
510 c.br.Reset(c.body[c.pc+1:])
511 bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures)
512 if err != nil {
513 return fmt.Errorf("reading block type for if instruction: %w", err)
514 }
515 c.pc += num
516
517 if c.unreachableState.on {
518 // If it is currently in unreachable,
519 // just remove the entire block.
520 c.unreachableState.depth++
521 break operatorSwitch
522 }
523
524 // Create a new frame -- entering if.
525 frame := controlFrame{
526 frameID: c.nextFrameID(),
527 originalStackLenWithoutParam: len(c.stack) - len(bt.Params),
528 originalStackLenWithoutParamUint64: c.stackLenInUint64 - bt.ParamNumInUint64,
529 // Note this will be set to controlFrameKindIfWithElse
530 // when else opcode found later.
531 kind: controlFrameKindIfWithoutElse,
532 blockType: bt,
533 }
534 c.controlFrames.push(frame)
535
536 // Prep labels for if and else of this if.
537 thenLabel := newLabel(labelKindHeader, frame.frameID)
538 elseLabel := newLabel(labelKindElse, frame.frameID)
539 c.result.LabelCallers[thenLabel]++
540 c.result.LabelCallers[elseLabel]++
541
542 // Emit the branch operation to enter the then block.
543 c.emit(newOperationBrIf(thenLabel, elseLabel, nopinclusiveRange))
544 c.emit(newOperationLabel(thenLabel))
545 case wasm.OpcodeElse:
546 frame := c.controlFrames.top()
547 if c.unreachableState.on && c.unreachableState.depth > 0 {
548 // If it is currently in unreachable, and the nested if,
549 // just remove the entire else block.
550 break operatorSwitch
551 } else if c.unreachableState.on {
552 // If it is currently in unreachable, and the non-nested if,
553 // reset the stack so we can correctly handle the else block.
554 top := c.controlFrames.top()
555 c.stackSwitchAt(top)
556 top.kind = controlFrameKindIfWithElse
557
558 // Re-push the parameters to the if block so that else block can use them.
559 for _, t := range frame.blockType.Params {
560 c.stackPush(wasmValueTypeTounsignedType(t))
561 }
562
563 // We are no longer unreachable in else frame,
564 // so emit the correct label, and reset the unreachable state.
565 elseLabel := newLabel(labelKindElse, frame.frameID)
566 c.resetUnreachable()
567 c.emit(
568 newOperationLabel(elseLabel),
569 )
570 break operatorSwitch
571 }
572
573 // Change the Kind of this If block, indicating that
574 // the if has else block.
575 frame.kind = controlFrameKindIfWithElse
576
577 // We need to reset the stack so that
578 // the values pushed inside the then block
579 // do not affect the else block.
580 dropOp := newOperationDrop(c.getFrameDropRange(frame, false))
581
582 // Reset the stack manipulated by the then block, and re-push the block param types to the stack.
583
584 c.stackSwitchAt(frame)
585 for _, t := range frame.blockType.Params {
586 c.stackPush(wasmValueTypeTounsignedType(t))
587 }
588
589 // Prep labels for else and the continuation of this if block.
590 elseLabel := newLabel(labelKindElse, frame.frameID)
591 continuationLabel := newLabel(labelKindContinuation, frame.frameID)
592 c.result.LabelCallers[continuationLabel]++
593
594 // Emit the instructions for exiting the if loop,
595 // and then the initiation of else block.
596 c.emit(dropOp)
597 // Jump to the continuation of this block.
598 c.emit(newOperationBr(continuationLabel))
599 // Initiate the else block.
600 c.emit(newOperationLabel(elseLabel))
601 case wasm.OpcodeEnd:
602 if c.unreachableState.on && c.unreachableState.depth > 0 {
603 c.unreachableState.depth--
604 break operatorSwitch
605 } else if c.unreachableState.on {
606 c.resetUnreachable()
607
608 frame := c.controlFrames.pop()
609 if c.controlFrames.empty() {
610 return nil
611 }
612
613 c.stackSwitchAt(frame)
614 for _, t := range frame.blockType.Results {
615 c.stackPush(wasmValueTypeTounsignedType(t))
616 }
617
618 continuationLabel := newLabel(labelKindContinuation, frame.frameID)
619 if frame.kind == controlFrameKindIfWithoutElse {
620 // Emit the else label.
621 elseLabel := newLabel(labelKindElse, frame.frameID)
622 c.result.LabelCallers[continuationLabel]++
623 c.emit(newOperationLabel(elseLabel))
624 c.emit(newOperationBr(continuationLabel))
625 c.emit(newOperationLabel(continuationLabel))
626 } else {
627 c.emit(
628 newOperationLabel(continuationLabel),
629 )
630 }
631
632 break operatorSwitch
633 }
634
635 frame := c.controlFrames.pop()
636
637 // We need to reset the stack so that
638 // the values pushed inside the block.
639 dropOp := newOperationDrop(c.getFrameDropRange(frame, true))
640 c.stackSwitchAt(frame)
641
642 // Push the result types onto the stack.
643 for _, t := range frame.blockType.Results {
644 c.stackPush(wasmValueTypeTounsignedType(t))
645 }
646
647 // Emit the instructions according to the Kind of the current control frame.
648 switch frame.kind {
649 case controlFrameKindFunction:
650 if !c.controlFrames.empty() {
651 // Should never happen. If so, there's a bug in the translation.
652 panic("bug: found more function control frames")
653 }
654 // Return from function.
655 c.emit(dropOp)
656 c.emit(newOperationBr(newLabel(labelKindReturn, 0)))
657 case controlFrameKindIfWithoutElse:
658 // This case we have to emit "empty" else label.
659 elseLabel := newLabel(labelKindElse, frame.frameID)
660 continuationLabel := newLabel(labelKindContinuation, frame.frameID)
661 c.result.LabelCallers[continuationLabel] += 2
662 c.emit(dropOp)
663 c.emit(newOperationBr(continuationLabel))
664 // Emit the else which soon branches into the continuation.
665 c.emit(newOperationLabel(elseLabel))
666 c.emit(newOperationBr(continuationLabel))
667 // Initiate the continuation.
668 c.emit(newOperationLabel(continuationLabel))
669 case controlFrameKindBlockWithContinuationLabel,
670 controlFrameKindIfWithElse:
671 continuationLabel := newLabel(labelKindContinuation, frame.frameID)
672 c.result.LabelCallers[continuationLabel]++
673 c.emit(dropOp)
674 c.emit(newOperationBr(continuationLabel))
675 c.emit(newOperationLabel(continuationLabel))
676 case controlFrameKindLoop, controlFrameKindBlockWithoutContinuationLabel:
677 c.emit(
678 dropOp,
679 )
680 default:
681 // Should never happen. If so, there's a bug in the translation.
682 panic(fmt.Errorf("bug: invalid control frame Kind: 0x%x", frame.kind))
683 }
684
685 case wasm.OpcodeBr:
686 targetIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:])
687 if err != nil {
688 return fmt.Errorf("read the target for br_if: %w", err)
689 }
690 c.pc += n
691
692 if c.unreachableState.on {
693 // If it is currently in unreachable, br is no-op.
694 break operatorSwitch
695 }
696
697 targetFrame := c.controlFrames.get(int(targetIndex))
698 targetFrame.ensureContinuation()
699 dropOp := newOperationDrop(c.getFrameDropRange(targetFrame, false))
700 targetID := targetFrame.asLabel()
701 c.result.LabelCallers[targetID]++
702 c.emit(dropOp)
703 c.emit(newOperationBr(targetID))
704 // Br operation is stack-polymorphic, and mark the state as unreachable.
705 // That means subsequent instructions in the current control frame are "unreachable"
706 // and can be safely removed.
707 c.markUnreachable()
708 case wasm.OpcodeBrIf:
709 targetIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:])
710 if err != nil {
711 return fmt.Errorf("read the target for br_if: %w", err)
712 }
713 c.pc += n
714
715 if c.unreachableState.on {
716 // If it is currently in unreachable, br-if is no-op.
717 break operatorSwitch
718 }
719
720 targetFrame := c.controlFrames.get(int(targetIndex))
721 targetFrame.ensureContinuation()
722 drop := c.getFrameDropRange(targetFrame, false)
723 target := targetFrame.asLabel()
724 c.result.LabelCallers[target]++
725
726 continuationLabel := newLabel(labelKindHeader, c.nextFrameID())
727 c.result.LabelCallers[continuationLabel]++
728 c.emit(newOperationBrIf(target, continuationLabel, drop))
729 // Start emitting else block operations.
730 c.emit(newOperationLabel(continuationLabel))
731 case wasm.OpcodeBrTable:
732 c.br.Reset(c.body[c.pc+1:])
733 r := c.br
734 numTargets, n, err := leb128.DecodeUint32(r)
735 if err != nil {
736 return fmt.Errorf("error reading number of targets in br_table: %w", err)
737 }
738 c.pc += n
739
740 if c.unreachableState.on {
741 // If it is currently in unreachable, br_table is no-op.
742 // But before proceeding to the next instruction, we must advance the pc
743 // according to the number of br_table targets.
744 for i := uint32(0); i <= numTargets; i++ { // inclusive as we also need to read the index of default target.
745 _, n, err := leb128.DecodeUint32(r)
746 if err != nil {
747 return fmt.Errorf("error reading target %d in br_table: %w", i, err)
748 }
749 c.pc += n
750 }
751 break operatorSwitch
752 }
753
754 // Read the branch targets.
755 s := numTargets * 2
756 targetLabels := make([]uint64, 2+s) // (label, inclusiveRange) * (default+numTargets)
757 for i := uint32(0); i < s; i += 2 {
758 l, n, err := leb128.DecodeUint32(r)
759 if err != nil {
760 return fmt.Errorf("error reading target %d in br_table: %w", i, err)
761 }
762 c.pc += n
763 targetFrame := c.controlFrames.get(int(l))
764 targetFrame.ensureContinuation()
765 drop := c.getFrameDropRange(targetFrame, false)
766 targetLabel := targetFrame.asLabel()
767 targetLabels[i] = uint64(targetLabel)
768 targetLabels[i+1] = drop.AsU64()
769 c.result.LabelCallers[targetLabel]++
770 }
771
772 // Prep default target control frame.
773 l, n, err := leb128.DecodeUint32(r)
774 if err != nil {
775 return fmt.Errorf("error reading default target of br_table: %w", err)
776 }
777 c.pc += n
778 defaultTargetFrame := c.controlFrames.get(int(l))
779 defaultTargetFrame.ensureContinuation()
780 defaultTargetDrop := c.getFrameDropRange(defaultTargetFrame, false)
781 defaultLabel := defaultTargetFrame.asLabel()
782 c.result.LabelCallers[defaultLabel]++
783 targetLabels[s] = uint64(defaultLabel)
784 targetLabels[s+1] = defaultTargetDrop.AsU64()
785 c.emit(newOperationBrTable(targetLabels))
786
787 // br_table operation is stack-polymorphic, and mark the state as unreachable.
788 // That means subsequent instructions in the current control frame are "unreachable"
789 // and can be safely removed.
790 c.markUnreachable()
791 case wasm.OpcodeReturn:
792 functionFrame := c.controlFrames.functionFrame()
793 dropOp := newOperationDrop(c.getFrameDropRange(functionFrame, false))
794
795 // Cleanup the stack and then jmp to function frame's continuation (meaning return).
796 c.emit(dropOp)
797 c.emit(newOperationBr(functionFrame.asLabel()))
798
799 // Return operation is stack-polymorphic, and mark the state as unreachable.
800 // That means subsequent instructions in the current control frame are "unreachable"
801 // and can be safely removed.
802 c.markUnreachable()
803 case wasm.OpcodeCall:
804 c.emit(
805 newOperationCall(index),
806 )
807 case wasm.OpcodeCallIndirect:
808 typeIndex := index
809 tableIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:])
810 if err != nil {
811 return fmt.Errorf("read target for br_table: %w", err)
812 }
813 c.pc += n
814 c.emit(
815 newOperationCallIndirect(typeIndex, tableIndex),
816 )
817 case wasm.OpcodeDrop:
818 r := inclusiveRange{Start: 0, End: 0}
819 if peekValueType == unsignedTypeV128 {
820 // inclusiveRange is the range in uint64 representation, so dropping a vector value on top
821 // should be translated as drop [0..1] inclusively.
822 r.End++
823 }
824 c.emit(newOperationDrop(r))
825 case wasm.OpcodeSelect:
826 // If it is on the unreachable state, ignore the instruction.
827 if c.unreachableState.on {
828 break operatorSwitch
829 }
830 isTargetVector := c.stackPeek() == unsignedTypeV128
831 c.emit(
832 newOperationSelect(isTargetVector),
833 )
834 case wasm.OpcodeTypedSelect:
835 // Skips two bytes: vector size fixed to 1, and the value type for select.
836 c.pc += 2
837 // If it is on the unreachable state, ignore the instruction.
838 if c.unreachableState.on {
839 break operatorSwitch
840 }
841 // Typed select is semantically equivalent to select at runtime.
842 isTargetVector := c.stackPeek() == unsignedTypeV128
843 c.emit(
844 newOperationSelect(isTargetVector),
845 )
846 case wasm.OpcodeLocalGet:
847 depth := c.localDepth(index)
848 if isVector := c.localType(index) == wasm.ValueTypeV128; !isVector {
849 c.emit(
850 // -1 because we already manipulated the stack before
851 // called localDepth ^^.
852 newOperationPick(depth-1, isVector),
853 )
854 } else {
855 c.emit(
856 // -2 because we already manipulated the stack before
857 // called localDepth ^^.
858 newOperationPick(depth-2, isVector),
859 )
860 }
861 case wasm.OpcodeLocalSet:
862 depth := c.localDepth(index)
863
864 isVector := c.localType(index) == wasm.ValueTypeV128
865 if isVector {
866 c.emit(
867 // +2 because we already popped the operands for this operation from the c.stack before
868 // called localDepth ^^,
869 newOperationSet(depth+2, isVector),
870 )
871 } else {
872 c.emit(
873 // +1 because we already popped the operands for this operation from the c.stack before
874 // called localDepth ^^,
875 newOperationSet(depth+1, isVector),
876 )
877 }
878 case wasm.OpcodeLocalTee:
879 depth := c.localDepth(index)
880 isVector := c.localType(index) == wasm.ValueTypeV128
881 if isVector {
882 c.emit(newOperationPick(1, isVector))
883 c.emit(newOperationSet(depth+2, isVector))
884 } else {
885 c.emit(
886 newOperationPick(0, isVector))
887 c.emit(newOperationSet(depth+1, isVector))
888 }
889 case wasm.OpcodeGlobalGet:
890 c.emit(
891 newOperationGlobalGet(index),
892 )
893 case wasm.OpcodeGlobalSet:
894 c.emit(
895 newOperationGlobalSet(index),
896 )
897 case wasm.OpcodeI32Load:
898 imm, err := c.readMemoryArg(wasm.OpcodeI32LoadName)
899 if err != nil {
900 return err
901 }
902 c.emit(newOperationLoad(unsignedTypeI32, imm))
903 case wasm.OpcodeI64Load:
904 imm, err := c.readMemoryArg(wasm.OpcodeI64LoadName)
905 if err != nil {
906 return err
907 }
908 c.emit(newOperationLoad(unsignedTypeI64, imm))
909 case wasm.OpcodeF32Load:
910 imm, err := c.readMemoryArg(wasm.OpcodeF32LoadName)
911 if err != nil {
912 return err
913 }
914 c.emit(newOperationLoad(unsignedTypeF32, imm))
915 case wasm.OpcodeF64Load:
916 imm, err := c.readMemoryArg(wasm.OpcodeF64LoadName)
917 if err != nil {
918 return err
919 }
920 c.emit(newOperationLoad(unsignedTypeF64, imm))
921 case wasm.OpcodeI32Load8S:
922 imm, err := c.readMemoryArg(wasm.OpcodeI32Load8SName)
923 if err != nil {
924 return err
925 }
926 c.emit(newOperationLoad8(signedInt32, imm))
927 case wasm.OpcodeI32Load8U:
928 imm, err := c.readMemoryArg(wasm.OpcodeI32Load8UName)
929 if err != nil {
930 return err
931 }
932 c.emit(newOperationLoad8(signedUint32, imm))
933 case wasm.OpcodeI32Load16S:
934 imm, err := c.readMemoryArg(wasm.OpcodeI32Load16SName)
935 if err != nil {
936 return err
937 }
938 c.emit(newOperationLoad16(signedInt32, imm))
939 case wasm.OpcodeI32Load16U:
940 imm, err := c.readMemoryArg(wasm.OpcodeI32Load16UName)
941 if err != nil {
942 return err
943 }
944 c.emit(newOperationLoad16(signedUint32, imm))
945 case wasm.OpcodeI64Load8S:
946 imm, err := c.readMemoryArg(wasm.OpcodeI64Load8SName)
947 if err != nil {
948 return err
949 }
950 c.emit(newOperationLoad8(signedInt64, imm))
951 case wasm.OpcodeI64Load8U:
952 imm, err := c.readMemoryArg(wasm.OpcodeI64Load8UName)
953 if err != nil {
954 return err
955 }
956 c.emit(newOperationLoad8(signedUint64, imm))
957 case wasm.OpcodeI64Load16S:
958 imm, err := c.readMemoryArg(wasm.OpcodeI64Load16SName)
959 if err != nil {
960 return err
961 }
962 c.emit(newOperationLoad16(signedInt64, imm))
963 case wasm.OpcodeI64Load16U:
964 imm, err := c.readMemoryArg(wasm.OpcodeI64Load16UName)
965 if err != nil {
966 return err
967 }
968 c.emit(newOperationLoad16(signedUint64, imm))
969 case wasm.OpcodeI64Load32S:
970 imm, err := c.readMemoryArg(wasm.OpcodeI64Load32SName)
971 if err != nil {
972 return err
973 }
974 c.emit(newOperationLoad32(true, imm))
975 case wasm.OpcodeI64Load32U:
976 imm, err := c.readMemoryArg(wasm.OpcodeI64Load32UName)
977 if err != nil {
978 return err
979 }
980 c.emit(newOperationLoad32(false, imm))
981 case wasm.OpcodeI32Store:
982 imm, err := c.readMemoryArg(wasm.OpcodeI32StoreName)
983 if err != nil {
984 return err
985 }
986 c.emit(
987 newOperationStore(unsignedTypeI32, imm),
988 )
989 case wasm.OpcodeI64Store:
990 imm, err := c.readMemoryArg(wasm.OpcodeI64StoreName)
991 if err != nil {
992 return err
993 }
994 c.emit(
995 newOperationStore(unsignedTypeI64, imm),
996 )
997 case wasm.OpcodeF32Store:
998 imm, err := c.readMemoryArg(wasm.OpcodeF32StoreName)
999 if err != nil {
1000 return err
1001 }
1002 c.emit(
1003 newOperationStore(unsignedTypeF32, imm),
1004 )
1005 case wasm.OpcodeF64Store:
1006 imm, err := c.readMemoryArg(wasm.OpcodeF64StoreName)
1007 if err != nil {
1008 return err
1009 }
1010 c.emit(
1011 newOperationStore(unsignedTypeF64, imm),
1012 )
1013 case wasm.OpcodeI32Store8:
1014 imm, err := c.readMemoryArg(wasm.OpcodeI32Store8Name)
1015 if err != nil {
1016 return err
1017 }
1018 c.emit(
1019 newOperationStore8(imm),
1020 )
1021 case wasm.OpcodeI32Store16:
1022 imm, err := c.readMemoryArg(wasm.OpcodeI32Store16Name)
1023 if err != nil {
1024 return err
1025 }
1026 c.emit(
1027 newOperationStore16(imm),
1028 )
1029 case wasm.OpcodeI64Store8:
1030 imm, err := c.readMemoryArg(wasm.OpcodeI64Store8Name)
1031 if err != nil {
1032 return err
1033 }
1034 c.emit(
1035 newOperationStore8(imm),
1036 )
1037 case wasm.OpcodeI64Store16:
1038 imm, err := c.readMemoryArg(wasm.OpcodeI64Store16Name)
1039 if err != nil {
1040 return err
1041 }
1042 c.emit(
1043 newOperationStore16(imm),
1044 )
1045 case wasm.OpcodeI64Store32:
1046 imm, err := c.readMemoryArg(wasm.OpcodeI64Store32Name)
1047 if err != nil {
1048 return err
1049 }
1050 c.emit(
1051 newOperationStore32(imm),
1052 )
1053 case wasm.OpcodeMemorySize:
1054 c.result.UsesMemory = true
1055 c.pc++ // Skip the reserved one byte.
1056 c.emit(
1057 newOperationMemorySize(),
1058 )
1059 case wasm.OpcodeMemoryGrow:
1060 c.result.UsesMemory = true
1061 c.pc++ // Skip the reserved one byte.
1062 c.emit(
1063 newOperationMemoryGrow(),
1064 )
1065 case wasm.OpcodeI32Const:
1066 val, num, err := leb128.LoadInt32(c.body[c.pc+1:])
1067 if err != nil {
1068 return fmt.Errorf("reading i32.const value: %v", err)
1069 }
1070 c.pc += num
1071 c.emit(
1072 newOperationConstI32(uint32(val)),
1073 )
1074 case wasm.OpcodeI64Const:
1075 val, num, err := leb128.LoadInt64(c.body[c.pc+1:])
1076 if err != nil {
1077 return fmt.Errorf("reading i64.const value: %v", err)
1078 }
1079 c.pc += num
1080 c.emit(
1081 newOperationConstI64(uint64(val)),
1082 )
1083 case wasm.OpcodeF32Const:
1084 v := math.Float32frombits(binary.LittleEndian.Uint32(c.body[c.pc+1:]))
1085 c.pc += 4
1086 c.emit(
1087 newOperationConstF32(v),
1088 )
1089 case wasm.OpcodeF64Const:
1090 v := math.Float64frombits(binary.LittleEndian.Uint64(c.body[c.pc+1:]))
1091 c.pc += 8
1092 c.emit(
1093 newOperationConstF64(v),
1094 )
1095 case wasm.OpcodeI32Eqz:
1096 c.emit(
1097 newOperationEqz(unsignedInt32),
1098 )
1099 case wasm.OpcodeI32Eq:
1100 c.emit(
1101 newOperationEq(unsignedTypeI32),
1102 )
1103 case wasm.OpcodeI32Ne:
1104 c.emit(
1105 newOperationNe(unsignedTypeI32),
1106 )
1107 case wasm.OpcodeI32LtS:
1108 c.emit(
1109 newOperationLt(signedTypeInt32),
1110 )
1111 case wasm.OpcodeI32LtU:
1112 c.emit(
1113 newOperationLt(signedTypeUint32),
1114 )
1115 case wasm.OpcodeI32GtS:
1116 c.emit(
1117 newOperationGt(signedTypeInt32),
1118 )
1119 case wasm.OpcodeI32GtU:
1120 c.emit(
1121 newOperationGt(signedTypeUint32),
1122 )
1123 case wasm.OpcodeI32LeS:
1124 c.emit(
1125 newOperationLe(signedTypeInt32),
1126 )
1127 case wasm.OpcodeI32LeU:
1128 c.emit(
1129 newOperationLe(signedTypeUint32),
1130 )
1131 case wasm.OpcodeI32GeS:
1132 c.emit(
1133 newOperationGe(signedTypeInt32),
1134 )
1135 case wasm.OpcodeI32GeU:
1136 c.emit(
1137 newOperationGe(signedTypeUint32),
1138 )
1139 case wasm.OpcodeI64Eqz:
1140 c.emit(
1141 newOperationEqz(unsignedInt64),
1142 )
1143 case wasm.OpcodeI64Eq:
1144 c.emit(
1145 newOperationEq(unsignedTypeI64),
1146 )
1147 case wasm.OpcodeI64Ne:
1148 c.emit(
1149 newOperationNe(unsignedTypeI64),
1150 )
1151 case wasm.OpcodeI64LtS:
1152 c.emit(
1153 newOperationLt(signedTypeInt64),
1154 )
1155 case wasm.OpcodeI64LtU:
1156 c.emit(
1157 newOperationLt(signedTypeUint64),
1158 )
1159 case wasm.OpcodeI64GtS:
1160 c.emit(
1161 newOperationGt(signedTypeInt64),
1162 )
1163 case wasm.OpcodeI64GtU:
1164 c.emit(
1165 newOperationGt(signedTypeUint64),
1166 )
1167 case wasm.OpcodeI64LeS:
1168 c.emit(
1169 newOperationLe(signedTypeInt64),
1170 )
1171 case wasm.OpcodeI64LeU:
1172 c.emit(
1173 newOperationLe(signedTypeUint64),
1174 )
1175 case wasm.OpcodeI64GeS:
1176 c.emit(
1177 newOperationGe(signedTypeInt64),
1178 )
1179 case wasm.OpcodeI64GeU:
1180 c.emit(
1181 newOperationGe(signedTypeUint64),
1182 )
1183 case wasm.OpcodeF32Eq:
1184 c.emit(
1185 newOperationEq(unsignedTypeF32),
1186 )
1187 case wasm.OpcodeF32Ne:
1188 c.emit(
1189 newOperationNe(unsignedTypeF32),
1190 )
1191 case wasm.OpcodeF32Lt:
1192 c.emit(
1193 newOperationLt(signedTypeFloat32),
1194 )
1195 case wasm.OpcodeF32Gt:
1196 c.emit(
1197 newOperationGt(signedTypeFloat32),
1198 )
1199 case wasm.OpcodeF32Le:
1200 c.emit(
1201 newOperationLe(signedTypeFloat32),
1202 )
1203 case wasm.OpcodeF32Ge:
1204 c.emit(
1205 newOperationGe(signedTypeFloat32),
1206 )
1207 case wasm.OpcodeF64Eq:
1208 c.emit(
1209 newOperationEq(unsignedTypeF64),
1210 )
1211 case wasm.OpcodeF64Ne:
1212 c.emit(
1213 newOperationNe(unsignedTypeF64),
1214 )
1215 case wasm.OpcodeF64Lt:
1216 c.emit(
1217 newOperationLt(signedTypeFloat64),
1218 )
1219 case wasm.OpcodeF64Gt:
1220 c.emit(
1221 newOperationGt(signedTypeFloat64),
1222 )
1223 case wasm.OpcodeF64Le:
1224 c.emit(
1225 newOperationLe(signedTypeFloat64),
1226 )
1227 case wasm.OpcodeF64Ge:
1228 c.emit(
1229 newOperationGe(signedTypeFloat64),
1230 )
1231 case wasm.OpcodeI32Clz:
1232 c.emit(
1233 newOperationClz(unsignedInt32),
1234 )
1235 case wasm.OpcodeI32Ctz:
1236 c.emit(
1237 newOperationCtz(unsignedInt32),
1238 )
1239 case wasm.OpcodeI32Popcnt:
1240 c.emit(
1241 newOperationPopcnt(unsignedInt32),
1242 )
1243 case wasm.OpcodeI32Add:
1244 c.emit(
1245 newOperationAdd(unsignedTypeI32),
1246 )
1247 case wasm.OpcodeI32Sub:
1248 c.emit(
1249 newOperationSub(unsignedTypeI32),
1250 )
1251 case wasm.OpcodeI32Mul:
1252 c.emit(
1253 newOperationMul(unsignedTypeI32),
1254 )
1255 case wasm.OpcodeI32DivS:
1256 c.emit(
1257 newOperationDiv(signedTypeInt32),
1258 )
1259 case wasm.OpcodeI32DivU:
1260 c.emit(
1261 newOperationDiv(signedTypeUint32),
1262 )
1263 case wasm.OpcodeI32RemS:
1264 c.emit(
1265 newOperationRem(signedInt32),
1266 )
1267 case wasm.OpcodeI32RemU:
1268 c.emit(
1269 newOperationRem(signedUint32),
1270 )
1271 case wasm.OpcodeI32And:
1272 c.emit(
1273 newOperationAnd(unsignedInt32),
1274 )
1275 case wasm.OpcodeI32Or:
1276 c.emit(
1277 newOperationOr(unsignedInt32),
1278 )
1279 case wasm.OpcodeI32Xor:
1280 c.emit(
1281 newOperationXor(unsignedInt64),
1282 )
1283 case wasm.OpcodeI32Shl:
1284 c.emit(
1285 newOperationShl(unsignedInt32),
1286 )
1287 case wasm.OpcodeI32ShrS:
1288 c.emit(
1289 newOperationShr(signedInt32),
1290 )
1291 case wasm.OpcodeI32ShrU:
1292 c.emit(
1293 newOperationShr(signedUint32),
1294 )
1295 case wasm.OpcodeI32Rotl:
1296 c.emit(
1297 newOperationRotl(unsignedInt32),
1298 )
1299 case wasm.OpcodeI32Rotr:
1300 c.emit(
1301 newOperationRotr(unsignedInt32),
1302 )
1303 case wasm.OpcodeI64Clz:
1304 c.emit(
1305 newOperationClz(unsignedInt64),
1306 )
1307 case wasm.OpcodeI64Ctz:
1308 c.emit(
1309 newOperationCtz(unsignedInt64),
1310 )
1311 case wasm.OpcodeI64Popcnt:
1312 c.emit(
1313 newOperationPopcnt(unsignedInt64),
1314 )
1315 case wasm.OpcodeI64Add:
1316 c.emit(
1317 newOperationAdd(unsignedTypeI64),
1318 )
1319 case wasm.OpcodeI64Sub:
1320 c.emit(
1321 newOperationSub(unsignedTypeI64),
1322 )
1323 case wasm.OpcodeI64Mul:
1324 c.emit(
1325 newOperationMul(unsignedTypeI64),
1326 )
1327 case wasm.OpcodeI64DivS:
1328 c.emit(
1329 newOperationDiv(signedTypeInt64),
1330 )
1331 case wasm.OpcodeI64DivU:
1332 c.emit(
1333 newOperationDiv(signedTypeUint64),
1334 )
1335 case wasm.OpcodeI64RemS:
1336 c.emit(
1337 newOperationRem(signedInt64),
1338 )
1339 case wasm.OpcodeI64RemU:
1340 c.emit(
1341 newOperationRem(signedUint64),
1342 )
1343 case wasm.OpcodeI64And:
1344 c.emit(
1345 newOperationAnd(unsignedInt64),
1346 )
1347 case wasm.OpcodeI64Or:
1348 c.emit(
1349 newOperationOr(unsignedInt64),
1350 )
1351 case wasm.OpcodeI64Xor:
1352 c.emit(
1353 newOperationXor(unsignedInt64),
1354 )
1355 case wasm.OpcodeI64Shl:
1356 c.emit(
1357 newOperationShl(unsignedInt64),
1358 )
1359 case wasm.OpcodeI64ShrS:
1360 c.emit(
1361 newOperationShr(signedInt64),
1362 )
1363 case wasm.OpcodeI64ShrU:
1364 c.emit(
1365 newOperationShr(signedUint64),
1366 )
1367 case wasm.OpcodeI64Rotl:
1368 c.emit(
1369 newOperationRotl(unsignedInt64),
1370 )
1371 case wasm.OpcodeI64Rotr:
1372 c.emit(
1373 newOperationRotr(unsignedInt64),
1374 )
1375 case wasm.OpcodeF32Abs:
1376 c.emit(
1377 newOperationAbs(f32),
1378 )
1379 case wasm.OpcodeF32Neg:
1380 c.emit(
1381 newOperationNeg(f32),
1382 )
1383 case wasm.OpcodeF32Ceil:
1384 c.emit(
1385 newOperationCeil(f32),
1386 )
1387 case wasm.OpcodeF32Floor:
1388 c.emit(
1389 newOperationFloor(f32),
1390 )
1391 case wasm.OpcodeF32Trunc:
1392 c.emit(
1393 newOperationTrunc(f32),
1394 )
1395 case wasm.OpcodeF32Nearest:
1396 c.emit(
1397 newOperationNearest(f32),
1398 )
1399 case wasm.OpcodeF32Sqrt:
1400 c.emit(
1401 newOperationSqrt(f32),
1402 )
1403 case wasm.OpcodeF32Add:
1404 c.emit(
1405 newOperationAdd(unsignedTypeF32),
1406 )
1407 case wasm.OpcodeF32Sub:
1408 c.emit(
1409 newOperationSub(unsignedTypeF32),
1410 )
1411 case wasm.OpcodeF32Mul:
1412 c.emit(
1413 newOperationMul(unsignedTypeF32),
1414 )
1415 case wasm.OpcodeF32Div:
1416 c.emit(
1417 newOperationDiv(signedTypeFloat32),
1418 )
1419 case wasm.OpcodeF32Min:
1420 c.emit(
1421 newOperationMin(f32),
1422 )
1423 case wasm.OpcodeF32Max:
1424 c.emit(
1425 newOperationMax(f32),
1426 )
1427 case wasm.OpcodeF32Copysign:
1428 c.emit(
1429 newOperationCopysign(f32),
1430 )
1431 case wasm.OpcodeF64Abs:
1432 c.emit(
1433 newOperationAbs(f64),
1434 )
1435 case wasm.OpcodeF64Neg:
1436 c.emit(
1437 newOperationNeg(f64),
1438 )
1439 case wasm.OpcodeF64Ceil:
1440 c.emit(
1441 newOperationCeil(f64),
1442 )
1443 case wasm.OpcodeF64Floor:
1444 c.emit(
1445 newOperationFloor(f64),
1446 )
1447 case wasm.OpcodeF64Trunc:
1448 c.emit(
1449 newOperationTrunc(f64),
1450 )
1451 case wasm.OpcodeF64Nearest:
1452 c.emit(
1453 newOperationNearest(f64),
1454 )
1455 case wasm.OpcodeF64Sqrt:
1456 c.emit(
1457 newOperationSqrt(f64),
1458 )
1459 case wasm.OpcodeF64Add:
1460 c.emit(
1461 newOperationAdd(unsignedTypeF64),
1462 )
1463 case wasm.OpcodeF64Sub:
1464 c.emit(
1465 newOperationSub(unsignedTypeF64),
1466 )
1467 case wasm.OpcodeF64Mul:
1468 c.emit(
1469 newOperationMul(unsignedTypeF64),
1470 )
1471 case wasm.OpcodeF64Div:
1472 c.emit(
1473 newOperationDiv(signedTypeFloat64),
1474 )
1475 case wasm.OpcodeF64Min:
1476 c.emit(
1477 newOperationMin(f64),
1478 )
1479 case wasm.OpcodeF64Max:
1480 c.emit(
1481 newOperationMax(f64),
1482 )
1483 case wasm.OpcodeF64Copysign:
1484 c.emit(
1485 newOperationCopysign(f64),
1486 )
1487 case wasm.OpcodeI32WrapI64:
1488 c.emit(
1489 newOperationI32WrapFromI64(),
1490 )
1491 case wasm.OpcodeI32TruncF32S:
1492 c.emit(
1493 newOperationITruncFromF(f32, signedInt32, false),
1494 )
1495 case wasm.OpcodeI32TruncF32U:
1496 c.emit(
1497 newOperationITruncFromF(f32, signedUint32, false),
1498 )
1499 case wasm.OpcodeI32TruncF64S:
1500 c.emit(
1501 newOperationITruncFromF(f64, signedInt32, false),
1502 )
1503 case wasm.OpcodeI32TruncF64U:
1504 c.emit(
1505 newOperationITruncFromF(f64, signedUint32, false),
1506 )
1507 case wasm.OpcodeI64ExtendI32S:
1508 c.emit(
1509 newOperationExtend(true),
1510 )
1511 case wasm.OpcodeI64ExtendI32U:
1512 c.emit(
1513 newOperationExtend(false),
1514 )
1515 case wasm.OpcodeI64TruncF32S:
1516 c.emit(
1517 newOperationITruncFromF(f32, signedInt64, false),
1518 )
1519 case wasm.OpcodeI64TruncF32U:
1520 c.emit(
1521 newOperationITruncFromF(f32, signedUint64, false),
1522 )
1523 case wasm.OpcodeI64TruncF64S:
1524 c.emit(
1525 newOperationITruncFromF(f64, signedInt64, false),
1526 )
1527 case wasm.OpcodeI64TruncF64U:
1528 c.emit(
1529 newOperationITruncFromF(f64, signedUint64, false),
1530 )
1531 case wasm.OpcodeF32ConvertI32S:
1532 c.emit(
1533 newOperationFConvertFromI(signedInt32, f32),
1534 )
1535 case wasm.OpcodeF32ConvertI32U:
1536 c.emit(
1537 newOperationFConvertFromI(signedUint32, f32),
1538 )
1539 case wasm.OpcodeF32ConvertI64S:
1540 c.emit(
1541 newOperationFConvertFromI(signedInt64, f32),
1542 )
1543 case wasm.OpcodeF32ConvertI64U:
1544 c.emit(
1545 newOperationFConvertFromI(signedUint64, f32),
1546 )
1547 case wasm.OpcodeF32DemoteF64:
1548 c.emit(
1549 newOperationF32DemoteFromF64(),
1550 )
1551 case wasm.OpcodeF64ConvertI32S:
1552 c.emit(
1553 newOperationFConvertFromI(signedInt32, f64),
1554 )
1555 case wasm.OpcodeF64ConvertI32U:
1556 c.emit(
1557 newOperationFConvertFromI(signedUint32, f64),
1558 )
1559 case wasm.OpcodeF64ConvertI64S:
1560 c.emit(
1561 newOperationFConvertFromI(signedInt64, f64),
1562 )
1563 case wasm.OpcodeF64ConvertI64U:
1564 c.emit(
1565 newOperationFConvertFromI(signedUint64, f64),
1566 )
1567 case wasm.OpcodeF64PromoteF32:
1568 c.emit(
1569 newOperationF64PromoteFromF32(),
1570 )
1571 case wasm.OpcodeI32ReinterpretF32:
1572 c.emit(
1573 newOperationI32ReinterpretFromF32(),
1574 )
1575 case wasm.OpcodeI64ReinterpretF64:
1576 c.emit(
1577 newOperationI64ReinterpretFromF64(),
1578 )
1579 case wasm.OpcodeF32ReinterpretI32:
1580 c.emit(
1581 newOperationF32ReinterpretFromI32(),
1582 )
1583 case wasm.OpcodeF64ReinterpretI64:
1584 c.emit(
1585 newOperationF64ReinterpretFromI64(),
1586 )
1587 case wasm.OpcodeI32Extend8S:
1588 c.emit(
1589 newOperationSignExtend32From8(),
1590 )
1591 case wasm.OpcodeI32Extend16S:
1592 c.emit(
1593 newOperationSignExtend32From16(),
1594 )
1595 case wasm.OpcodeI64Extend8S:
1596 c.emit(
1597 newOperationSignExtend64From8(),
1598 )
1599 case wasm.OpcodeI64Extend16S:
1600 c.emit(
1601 newOperationSignExtend64From16(),
1602 )
1603 case wasm.OpcodeI64Extend32S:
1604 c.emit(
1605 newOperationSignExtend64From32(),
1606 )
1607 case wasm.OpcodeRefFunc:
1608 c.pc++
1609 index, num, err := leb128.LoadUint32(c.body[c.pc:])
1610 if err != nil {
1611 return fmt.Errorf("failed to read function index for ref.func: %v", err)
1612 }
1613 c.pc += num - 1
1614 c.emit(
1615 newOperationRefFunc(index),
1616 )
1617 case wasm.OpcodeRefNull:
1618 c.pc++ // Skip the type of reftype as every ref value is opaque pointer.
1619 c.emit(
1620 newOperationConstI64(0),
1621 )
1622 case wasm.OpcodeRefIsNull:
1623 // Simply compare the opaque pointer (i64) with zero.
1624 c.emit(
1625 newOperationEqz(unsignedInt64),
1626 )
1627 case wasm.OpcodeTableGet:
1628 c.pc++
1629 tableIndex, num, err := leb128.LoadUint32(c.body[c.pc:])
1630 if err != nil {
1631 return fmt.Errorf("failed to read function index for table.get: %v", err)
1632 }
1633 c.pc += num - 1
1634 c.emit(
1635 newOperationTableGet(tableIndex),
1636 )
1637 case wasm.OpcodeTableSet:
1638 c.pc++
1639 tableIndex, num, err := leb128.LoadUint32(c.body[c.pc:])
1640 if err != nil {
1641 return fmt.Errorf("failed to read function index for table.set: %v", err)
1642 }
1643 c.pc += num - 1
1644 c.emit(
1645 newOperationTableSet(tableIndex),
1646 )
1647 case wasm.OpcodeMiscPrefix:
1648 c.pc++
1649 // A misc opcode is encoded as an unsigned variable 32-bit integer.
1650 miscOp, num, err := leb128.LoadUint32(c.body[c.pc:])
1651 if err != nil {
1652 return fmt.Errorf("failed to read misc opcode: %v", err)
1653 }
1654 c.pc += num - 1
1655 switch byte(miscOp) {
1656 case wasm.OpcodeMiscI32TruncSatF32S:
1657 c.emit(
1658 newOperationITruncFromF(f32, signedInt32, true),
1659 )
1660 case wasm.OpcodeMiscI32TruncSatF32U:
1661 c.emit(
1662 newOperationITruncFromF(f32, signedUint32, true),
1663 )
1664 case wasm.OpcodeMiscI32TruncSatF64S:
1665 c.emit(
1666 newOperationITruncFromF(f64, signedInt32, true),
1667 )
1668 case wasm.OpcodeMiscI32TruncSatF64U:
1669 c.emit(
1670 newOperationITruncFromF(f64, signedUint32, true),
1671 )
1672 case wasm.OpcodeMiscI64TruncSatF32S:
1673 c.emit(
1674 newOperationITruncFromF(f32, signedInt64, true),
1675 )
1676 case wasm.OpcodeMiscI64TruncSatF32U:
1677 c.emit(
1678 newOperationITruncFromF(f32, signedUint64, true),
1679 )
1680 case wasm.OpcodeMiscI64TruncSatF64S:
1681 c.emit(
1682 newOperationITruncFromF(f64, signedInt64, true),
1683 )
1684 case wasm.OpcodeMiscI64TruncSatF64U:
1685 c.emit(
1686 newOperationITruncFromF(f64, signedUint64, true),
1687 )
1688 case wasm.OpcodeMiscMemoryInit:
1689 c.result.UsesMemory = true
1690 dataIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
1691 if err != nil {
1692 return fmt.Errorf("reading i32.const value: %v", err)
1693 }
1694 c.pc += num + 1 // +1 to skip the memory index which is fixed to zero.
1695 c.emit(
1696 newOperationMemoryInit(dataIndex),
1697 )
1698 case wasm.OpcodeMiscDataDrop:
1699 dataIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
1700 if err != nil {
1701 return fmt.Errorf("reading i32.const value: %v", err)
1702 }
1703 c.pc += num
1704 c.emit(
1705 newOperationDataDrop(dataIndex),
1706 )
1707 case wasm.OpcodeMiscMemoryCopy:
1708 c.result.UsesMemory = true
1709 c.pc += 2 // +2 to skip two memory indexes which are fixed to zero.
1710 c.emit(
1711 newOperationMemoryCopy(),
1712 )
1713 case wasm.OpcodeMiscMemoryFill:
1714 c.result.UsesMemory = true
1715 c.pc += 1 // +1 to skip the memory index which is fixed to zero.
1716 c.emit(
1717 newOperationMemoryFill(),
1718 )
1719 case wasm.OpcodeMiscTableInit:
1720 elemIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
1721 if err != nil {
1722 return fmt.Errorf("reading i32.const value: %v", err)
1723 }
1724 c.pc += num
1725 // Read table index which is fixed to zero currently.
1726 tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
1727 if err != nil {
1728 return fmt.Errorf("reading i32.const value: %v", err)
1729 }
1730 c.pc += num
1731 c.emit(
1732 newOperationTableInit(elemIndex, tableIndex),
1733 )
1734 case wasm.OpcodeMiscElemDrop:
1735 elemIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
1736 if err != nil {
1737 return fmt.Errorf("reading i32.const value: %v", err)
1738 }
1739 c.pc += num
1740 c.emit(
1741 newOperationElemDrop(elemIndex),
1742 )
1743 case wasm.OpcodeMiscTableCopy:
1744 // Read the source table inde.g.
1745 dst, num, err := leb128.LoadUint32(c.body[c.pc+1:])
1746 if err != nil {
1747 return fmt.Errorf("reading i32.const value: %v", err)
1748 }
1749 c.pc += num
1750 // Read the destination table inde.g.
1751 src, num, err := leb128.LoadUint32(c.body[c.pc+1:])
1752 if err != nil {
1753 return fmt.Errorf("reading i32.const value: %v", err)
1754 }
1755 c.pc += num
1756 c.emit(
1757 newOperationTableCopy(src, dst),
1758 )
1759 case wasm.OpcodeMiscTableGrow:
1760 // Read the source table inde.g.
1761 tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
1762 if err != nil {
1763 return fmt.Errorf("reading i32.const value: %v", err)
1764 }
1765 c.pc += num
1766 c.emit(
1767 newOperationTableGrow(tableIndex),
1768 )
1769 case wasm.OpcodeMiscTableSize:
1770 // Read the source table inde.g.
1771 tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
1772 if err != nil {
1773 return fmt.Errorf("reading i32.const value: %v", err)
1774 }
1775 c.pc += num
1776 c.emit(
1777 newOperationTableSize(tableIndex),
1778 )
1779 case wasm.OpcodeMiscTableFill:
1780 // Read the source table index.
1781 tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
1782 if err != nil {
1783 return fmt.Errorf("reading i32.const value: %v", err)
1784 }
1785 c.pc += num
1786 c.emit(
1787 newOperationTableFill(tableIndex),
1788 )
1789 default:
1790 return fmt.Errorf("unsupported misc instruction in interpreterir: 0x%x", op)
1791 }
1792 case wasm.OpcodeVecPrefix:
1793 c.pc++
1794 switch vecOp := c.body[c.pc]; vecOp {
1795 case wasm.OpcodeVecV128Const:
1796 c.pc++
1797 lo := binary.LittleEndian.Uint64(c.body[c.pc : c.pc+8])
1798 c.pc += 8
1799 hi := binary.LittleEndian.Uint64(c.body[c.pc : c.pc+8])
1800 c.emit(
1801 newOperationV128Const(lo, hi),
1802 )
1803 c.pc += 7
1804 case wasm.OpcodeVecV128Load:
1805 arg, err := c.readMemoryArg(wasm.OpcodeI32LoadName)
1806 if err != nil {
1807 return err
1808 }
1809 c.emit(
1810 newOperationV128Load(v128LoadType128, arg),
1811 )
1812 case wasm.OpcodeVecV128Load8x8s:
1813 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8x8SName)
1814 if err != nil {
1815 return err
1816 }
1817 c.emit(
1818 newOperationV128Load(v128LoadType8x8s, arg),
1819 )
1820 case wasm.OpcodeVecV128Load8x8u:
1821 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8x8UName)
1822 if err != nil {
1823 return err
1824 }
1825 c.emit(
1826 newOperationV128Load(v128LoadType8x8u, arg),
1827 )
1828 case wasm.OpcodeVecV128Load16x4s:
1829 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16x4SName)
1830 if err != nil {
1831 return err
1832 }
1833 c.emit(
1834 newOperationV128Load(v128LoadType16x4s, arg),
1835 )
1836 case wasm.OpcodeVecV128Load16x4u:
1837 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16x4UName)
1838 if err != nil {
1839 return err
1840 }
1841 c.emit(
1842 newOperationV128Load(v128LoadType16x4u, arg),
1843 )
1844 case wasm.OpcodeVecV128Load32x2s:
1845 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32x2SName)
1846 if err != nil {
1847 return err
1848 }
1849 c.emit(
1850 newOperationV128Load(v128LoadType32x2s, arg),
1851 )
1852 case wasm.OpcodeVecV128Load32x2u:
1853 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32x2UName)
1854 if err != nil {
1855 return err
1856 }
1857 c.emit(
1858 newOperationV128Load(v128LoadType32x2u, arg),
1859 )
1860 case wasm.OpcodeVecV128Load8Splat:
1861 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8SplatName)
1862 if err != nil {
1863 return err
1864 }
1865 c.emit(
1866 newOperationV128Load(v128LoadType8Splat, arg),
1867 )
1868 case wasm.OpcodeVecV128Load16Splat:
1869 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16SplatName)
1870 if err != nil {
1871 return err
1872 }
1873 c.emit(
1874 newOperationV128Load(v128LoadType16Splat, arg),
1875 )
1876 case wasm.OpcodeVecV128Load32Splat:
1877 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32SplatName)
1878 if err != nil {
1879 return err
1880 }
1881 c.emit(
1882 newOperationV128Load(v128LoadType32Splat, arg),
1883 )
1884 case wasm.OpcodeVecV128Load64Splat:
1885 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64SplatName)
1886 if err != nil {
1887 return err
1888 }
1889 c.emit(
1890 newOperationV128Load(v128LoadType64Splat, arg),
1891 )
1892 case wasm.OpcodeVecV128Load32zero:
1893 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32zeroName)
1894 if err != nil {
1895 return err
1896 }
1897 c.emit(
1898 newOperationV128Load(v128LoadType32zero, arg),
1899 )
1900 case wasm.OpcodeVecV128Load64zero:
1901 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64zeroName)
1902 if err != nil {
1903 return err
1904 }
1905 c.emit(
1906 newOperationV128Load(v128LoadType64zero, arg),
1907 )
1908 case wasm.OpcodeVecV128Load8Lane:
1909 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8LaneName)
1910 if err != nil {
1911 return err
1912 }
1913 c.pc++
1914 laneIndex := c.body[c.pc]
1915 c.emit(
1916 newOperationV128LoadLane(laneIndex, 8, arg),
1917 )
1918 case wasm.OpcodeVecV128Load16Lane:
1919 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16LaneName)
1920 if err != nil {
1921 return err
1922 }
1923 c.pc++
1924 laneIndex := c.body[c.pc]
1925 c.emit(
1926 newOperationV128LoadLane(laneIndex, 16, arg),
1927 )
1928 case wasm.OpcodeVecV128Load32Lane:
1929 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32LaneName)
1930 if err != nil {
1931 return err
1932 }
1933 c.pc++
1934 laneIndex := c.body[c.pc]
1935 c.emit(
1936 newOperationV128LoadLane(laneIndex, 32, arg),
1937 )
1938 case wasm.OpcodeVecV128Load64Lane:
1939 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64LaneName)
1940 if err != nil {
1941 return err
1942 }
1943 c.pc++
1944 laneIndex := c.body[c.pc]
1945 c.emit(
1946 newOperationV128LoadLane(laneIndex, 64, arg),
1947 )
1948 case wasm.OpcodeVecV128Store:
1949 arg, err := c.readMemoryArg(wasm.OpcodeVecV128StoreName)
1950 if err != nil {
1951 return err
1952 }
1953 c.emit(
1954 newOperationV128Store(arg),
1955 )
1956 case wasm.OpcodeVecV128Store8Lane:
1957 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store8LaneName)
1958 if err != nil {
1959 return err
1960 }
1961 c.pc++
1962 laneIndex := c.body[c.pc]
1963 c.emit(
1964 newOperationV128StoreLane(laneIndex, 8, arg),
1965 )
1966 case wasm.OpcodeVecV128Store16Lane:
1967 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store16LaneName)
1968 if err != nil {
1969 return err
1970 }
1971 c.pc++
1972 laneIndex := c.body[c.pc]
1973 c.emit(
1974 newOperationV128StoreLane(laneIndex, 16, arg),
1975 )
1976 case wasm.OpcodeVecV128Store32Lane:
1977 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store32LaneName)
1978 if err != nil {
1979 return err
1980 }
1981 c.pc++
1982 laneIndex := c.body[c.pc]
1983 c.emit(
1984 newOperationV128StoreLane(laneIndex, 32, arg),
1985 )
1986 case wasm.OpcodeVecV128Store64Lane:
1987 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store64LaneName)
1988 if err != nil {
1989 return err
1990 }
1991 c.pc++
1992 laneIndex := c.body[c.pc]
1993 c.emit(
1994 newOperationV128StoreLane(laneIndex, 64, arg),
1995 )
1996 case wasm.OpcodeVecI8x16ExtractLaneS:
1997 c.pc++
1998 laneIndex := c.body[c.pc]
1999 c.emit(
2000 newOperationV128ExtractLane(laneIndex, true, shapeI8x16),
2001 )
2002 case wasm.OpcodeVecI8x16ExtractLaneU:
2003 c.pc++
2004 laneIndex := c.body[c.pc]
2005 c.emit(
2006 newOperationV128ExtractLane(laneIndex, false, shapeI8x16),
2007 )
2008 case wasm.OpcodeVecI16x8ExtractLaneS:
2009 c.pc++
2010 laneIndex := c.body[c.pc]
2011 c.emit(
2012 newOperationV128ExtractLane(laneIndex, true, shapeI16x8),
2013 )
2014 case wasm.OpcodeVecI16x8ExtractLaneU:
2015 c.pc++
2016 laneIndex := c.body[c.pc]
2017 c.emit(
2018 newOperationV128ExtractLane(laneIndex, false, shapeI16x8),
2019 )
2020 case wasm.OpcodeVecI32x4ExtractLane:
2021 c.pc++
2022 laneIndex := c.body[c.pc]
2023 c.emit(
2024 newOperationV128ExtractLane(laneIndex, false, shapeI32x4),
2025 )
2026 case wasm.OpcodeVecI64x2ExtractLane:
2027 c.pc++
2028 laneIndex := c.body[c.pc]
2029 c.emit(
2030 newOperationV128ExtractLane(laneIndex, false, shapeI64x2),
2031 )
2032 case wasm.OpcodeVecF32x4ExtractLane:
2033 c.pc++
2034 laneIndex := c.body[c.pc]
2035 c.emit(
2036 newOperationV128ExtractLane(laneIndex, false, shapeF32x4),
2037 )
2038 case wasm.OpcodeVecF64x2ExtractLane:
2039 c.pc++
2040 laneIndex := c.body[c.pc]
2041 c.emit(
2042 newOperationV128ExtractLane(laneIndex, false, shapeF64x2),
2043 )
2044 case wasm.OpcodeVecI8x16ReplaceLane:
2045 c.pc++
2046 laneIndex := c.body[c.pc]
2047 c.emit(
2048 newOperationV128ReplaceLane(laneIndex, shapeI8x16),
2049 )
2050 case wasm.OpcodeVecI16x8ReplaceLane:
2051 c.pc++
2052 laneIndex := c.body[c.pc]
2053 c.emit(
2054 newOperationV128ReplaceLane(laneIndex, shapeI16x8),
2055 )
2056 case wasm.OpcodeVecI32x4ReplaceLane:
2057 c.pc++
2058 laneIndex := c.body[c.pc]
2059 c.emit(
2060 newOperationV128ReplaceLane(laneIndex, shapeI32x4),
2061 )
2062 case wasm.OpcodeVecI64x2ReplaceLane:
2063 c.pc++
2064 laneIndex := c.body[c.pc]
2065 c.emit(
2066 newOperationV128ReplaceLane(laneIndex, shapeI64x2),
2067 )
2068 case wasm.OpcodeVecF32x4ReplaceLane:
2069 c.pc++
2070 laneIndex := c.body[c.pc]
2071 c.emit(
2072 newOperationV128ReplaceLane(laneIndex, shapeF32x4),
2073 )
2074 case wasm.OpcodeVecF64x2ReplaceLane:
2075 c.pc++
2076 laneIndex := c.body[c.pc]
2077 c.emit(
2078 newOperationV128ReplaceLane(laneIndex, shapeF64x2),
2079 )
2080 case wasm.OpcodeVecI8x16Splat:
2081 c.emit(
2082 newOperationV128Splat(shapeI8x16),
2083 )
2084 case wasm.OpcodeVecI16x8Splat:
2085 c.emit(
2086 newOperationV128Splat(shapeI16x8),
2087 )
2088 case wasm.OpcodeVecI32x4Splat:
2089 c.emit(
2090 newOperationV128Splat(shapeI32x4),
2091 )
2092 case wasm.OpcodeVecI64x2Splat:
2093 c.emit(
2094 newOperationV128Splat(shapeI64x2),
2095 )
2096 case wasm.OpcodeVecF32x4Splat:
2097 c.emit(
2098 newOperationV128Splat(shapeF32x4),
2099 )
2100 case wasm.OpcodeVecF64x2Splat:
2101 c.emit(
2102 newOperationV128Splat(shapeF64x2),
2103 )
2104 case wasm.OpcodeVecI8x16Swizzle:
2105 c.emit(
2106 newOperationV128Swizzle(),
2107 )
2108 case wasm.OpcodeVecV128i8x16Shuffle:
2109 c.pc++
2110 lanes := make([]uint64, 16)
2111 for i := uint64(0); i < 16; i++ {
2112 lanes[i] = uint64(c.body[c.pc+i])
2113 }
2114 op := newOperationV128Shuffle(lanes)
2115 c.emit(op)
2116 c.pc += 15
2117 case wasm.OpcodeVecV128AnyTrue:
2118 c.emit(
2119 newOperationV128AnyTrue(),
2120 )
2121 case wasm.OpcodeVecI8x16AllTrue:
2122 c.emit(
2123 newOperationV128AllTrue(shapeI8x16),
2124 )
2125 case wasm.OpcodeVecI16x8AllTrue:
2126 c.emit(
2127 newOperationV128AllTrue(shapeI16x8),
2128 )
2129 case wasm.OpcodeVecI32x4AllTrue:
2130 c.emit(
2131 newOperationV128AllTrue(shapeI32x4),
2132 )
2133 case wasm.OpcodeVecI64x2AllTrue:
2134 c.emit(
2135 newOperationV128AllTrue(shapeI64x2),
2136 )
2137 case wasm.OpcodeVecI8x16BitMask:
2138 c.emit(
2139 newOperationV128BitMask(shapeI8x16),
2140 )
2141 case wasm.OpcodeVecI16x8BitMask:
2142 c.emit(
2143 newOperationV128BitMask(shapeI16x8),
2144 )
2145 case wasm.OpcodeVecI32x4BitMask:
2146 c.emit(
2147 newOperationV128BitMask(shapeI32x4),
2148 )
2149 case wasm.OpcodeVecI64x2BitMask:
2150 c.emit(
2151 newOperationV128BitMask(shapeI64x2),
2152 )
2153 case wasm.OpcodeVecV128And:
2154 c.emit(
2155 newOperationV128And(),
2156 )
2157 case wasm.OpcodeVecV128Not:
2158 c.emit(
2159 newOperationV128Not(),
2160 )
2161 case wasm.OpcodeVecV128Or:
2162 c.emit(
2163 newOperationV128Or(),
2164 )
2165 case wasm.OpcodeVecV128Xor:
2166 c.emit(
2167 newOperationV128Xor(),
2168 )
2169 case wasm.OpcodeVecV128Bitselect:
2170 c.emit(
2171 newOperationV128Bitselect(),
2172 )
2173 case wasm.OpcodeVecV128AndNot:
2174 c.emit(
2175 newOperationV128AndNot(),
2176 )
2177 case wasm.OpcodeVecI8x16Shl:
2178 c.emit(
2179 newOperationV128Shl(shapeI8x16),
2180 )
2181 case wasm.OpcodeVecI8x16ShrS:
2182 c.emit(
2183 newOperationV128Shr(shapeI8x16, true),
2184 )
2185 case wasm.OpcodeVecI8x16ShrU:
2186 c.emit(
2187 newOperationV128Shr(shapeI8x16, false),
2188 )
2189 case wasm.OpcodeVecI16x8Shl:
2190 c.emit(
2191 newOperationV128Shl(shapeI16x8),
2192 )
2193 case wasm.OpcodeVecI16x8ShrS:
2194 c.emit(
2195 newOperationV128Shr(shapeI16x8, true),
2196 )
2197 case wasm.OpcodeVecI16x8ShrU:
2198 c.emit(
2199 newOperationV128Shr(shapeI16x8, false),
2200 )
2201 case wasm.OpcodeVecI32x4Shl:
2202 c.emit(
2203 newOperationV128Shl(shapeI32x4),
2204 )
2205 case wasm.OpcodeVecI32x4ShrS:
2206 c.emit(
2207 newOperationV128Shr(shapeI32x4, true),
2208 )
2209 case wasm.OpcodeVecI32x4ShrU:
2210 c.emit(
2211 newOperationV128Shr(shapeI32x4, false),
2212 )
2213 case wasm.OpcodeVecI64x2Shl:
2214 c.emit(
2215 newOperationV128Shl(shapeI64x2),
2216 )
2217 case wasm.OpcodeVecI64x2ShrS:
2218 c.emit(
2219 newOperationV128Shr(shapeI64x2, true),
2220 )
2221 case wasm.OpcodeVecI64x2ShrU:
2222 c.emit(
2223 newOperationV128Shr(shapeI64x2, false),
2224 )
2225 case wasm.OpcodeVecI8x16Eq:
2226 c.emit(
2227 newOperationV128Cmp(v128CmpTypeI8x16Eq),
2228 )
2229 case wasm.OpcodeVecI8x16Ne:
2230 c.emit(
2231 newOperationV128Cmp(v128CmpTypeI8x16Ne),
2232 )
2233 case wasm.OpcodeVecI8x16LtS:
2234 c.emit(
2235 newOperationV128Cmp(v128CmpTypeI8x16LtS),
2236 )
2237 case wasm.OpcodeVecI8x16LtU:
2238 c.emit(
2239 newOperationV128Cmp(v128CmpTypeI8x16LtU),
2240 )
2241 case wasm.OpcodeVecI8x16GtS:
2242 c.emit(
2243 newOperationV128Cmp(v128CmpTypeI8x16GtS),
2244 )
2245 case wasm.OpcodeVecI8x16GtU:
2246 c.emit(
2247 newOperationV128Cmp(v128CmpTypeI8x16GtU),
2248 )
2249 case wasm.OpcodeVecI8x16LeS:
2250 c.emit(
2251 newOperationV128Cmp(v128CmpTypeI8x16LeS),
2252 )
2253 case wasm.OpcodeVecI8x16LeU:
2254 c.emit(
2255 newOperationV128Cmp(v128CmpTypeI8x16LeU),
2256 )
2257 case wasm.OpcodeVecI8x16GeS:
2258 c.emit(
2259 newOperationV128Cmp(v128CmpTypeI8x16GeS),
2260 )
2261 case wasm.OpcodeVecI8x16GeU:
2262 c.emit(
2263 newOperationV128Cmp(v128CmpTypeI8x16GeU),
2264 )
2265 case wasm.OpcodeVecI16x8Eq:
2266 c.emit(
2267 newOperationV128Cmp(v128CmpTypeI16x8Eq),
2268 )
2269 case wasm.OpcodeVecI16x8Ne:
2270 c.emit(
2271 newOperationV128Cmp(v128CmpTypeI16x8Ne),
2272 )
2273 case wasm.OpcodeVecI16x8LtS:
2274 c.emit(
2275 newOperationV128Cmp(v128CmpTypeI16x8LtS),
2276 )
2277 case wasm.OpcodeVecI16x8LtU:
2278 c.emit(
2279 newOperationV128Cmp(v128CmpTypeI16x8LtU),
2280 )
2281 case wasm.OpcodeVecI16x8GtS:
2282 c.emit(
2283 newOperationV128Cmp(v128CmpTypeI16x8GtS),
2284 )
2285 case wasm.OpcodeVecI16x8GtU:
2286 c.emit(
2287 newOperationV128Cmp(v128CmpTypeI16x8GtU),
2288 )
2289 case wasm.OpcodeVecI16x8LeS:
2290 c.emit(
2291 newOperationV128Cmp(v128CmpTypeI16x8LeS),
2292 )
2293 case wasm.OpcodeVecI16x8LeU:
2294 c.emit(
2295 newOperationV128Cmp(v128CmpTypeI16x8LeU),
2296 )
2297 case wasm.OpcodeVecI16x8GeS:
2298 c.emit(
2299 newOperationV128Cmp(v128CmpTypeI16x8GeS),
2300 )
2301 case wasm.OpcodeVecI16x8GeU:
2302 c.emit(
2303 newOperationV128Cmp(v128CmpTypeI16x8GeU),
2304 )
2305 case wasm.OpcodeVecI32x4Eq:
2306 c.emit(
2307 newOperationV128Cmp(v128CmpTypeI32x4Eq),
2308 )
2309 case wasm.OpcodeVecI32x4Ne:
2310 c.emit(
2311 newOperationV128Cmp(v128CmpTypeI32x4Ne),
2312 )
2313 case wasm.OpcodeVecI32x4LtS:
2314 c.emit(
2315 newOperationV128Cmp(v128CmpTypeI32x4LtS),
2316 )
2317 case wasm.OpcodeVecI32x4LtU:
2318 c.emit(
2319 newOperationV128Cmp(v128CmpTypeI32x4LtU),
2320 )
2321 case wasm.OpcodeVecI32x4GtS:
2322 c.emit(
2323 newOperationV128Cmp(v128CmpTypeI32x4GtS),
2324 )
2325 case wasm.OpcodeVecI32x4GtU:
2326 c.emit(
2327 newOperationV128Cmp(v128CmpTypeI32x4GtU),
2328 )
2329 case wasm.OpcodeVecI32x4LeS:
2330 c.emit(
2331 newOperationV128Cmp(v128CmpTypeI32x4LeS),
2332 )
2333 case wasm.OpcodeVecI32x4LeU:
2334 c.emit(
2335 newOperationV128Cmp(v128CmpTypeI32x4LeU),
2336 )
2337 case wasm.OpcodeVecI32x4GeS:
2338 c.emit(
2339 newOperationV128Cmp(v128CmpTypeI32x4GeS),
2340 )
2341 case wasm.OpcodeVecI32x4GeU:
2342 c.emit(
2343 newOperationV128Cmp(v128CmpTypeI32x4GeU),
2344 )
2345 case wasm.OpcodeVecI64x2Eq:
2346 c.emit(
2347 newOperationV128Cmp(v128CmpTypeI64x2Eq),
2348 )
2349 case wasm.OpcodeVecI64x2Ne:
2350 c.emit(
2351 newOperationV128Cmp(v128CmpTypeI64x2Ne),
2352 )
2353 case wasm.OpcodeVecI64x2LtS:
2354 c.emit(
2355 newOperationV128Cmp(v128CmpTypeI64x2LtS),
2356 )
2357 case wasm.OpcodeVecI64x2GtS:
2358 c.emit(
2359 newOperationV128Cmp(v128CmpTypeI64x2GtS),
2360 )
2361 case wasm.OpcodeVecI64x2LeS:
2362 c.emit(
2363 newOperationV128Cmp(v128CmpTypeI64x2LeS),
2364 )
2365 case wasm.OpcodeVecI64x2GeS:
2366 c.emit(
2367 newOperationV128Cmp(v128CmpTypeI64x2GeS),
2368 )
2369 case wasm.OpcodeVecF32x4Eq:
2370 c.emit(
2371 newOperationV128Cmp(v128CmpTypeF32x4Eq),
2372 )
2373 case wasm.OpcodeVecF32x4Ne:
2374 c.emit(
2375 newOperationV128Cmp(v128CmpTypeF32x4Ne),
2376 )
2377 case wasm.OpcodeVecF32x4Lt:
2378 c.emit(
2379 newOperationV128Cmp(v128CmpTypeF32x4Lt),
2380 )
2381 case wasm.OpcodeVecF32x4Gt:
2382 c.emit(
2383 newOperationV128Cmp(v128CmpTypeF32x4Gt),
2384 )
2385 case wasm.OpcodeVecF32x4Le:
2386 c.emit(
2387 newOperationV128Cmp(v128CmpTypeF32x4Le),
2388 )
2389 case wasm.OpcodeVecF32x4Ge:
2390 c.emit(
2391 newOperationV128Cmp(v128CmpTypeF32x4Ge),
2392 )
2393 case wasm.OpcodeVecF64x2Eq:
2394 c.emit(
2395 newOperationV128Cmp(v128CmpTypeF64x2Eq),
2396 )
2397 case wasm.OpcodeVecF64x2Ne:
2398 c.emit(
2399 newOperationV128Cmp(v128CmpTypeF64x2Ne),
2400 )
2401 case wasm.OpcodeVecF64x2Lt:
2402 c.emit(
2403 newOperationV128Cmp(v128CmpTypeF64x2Lt),
2404 )
2405 case wasm.OpcodeVecF64x2Gt:
2406 c.emit(
2407 newOperationV128Cmp(v128CmpTypeF64x2Gt),
2408 )
2409 case wasm.OpcodeVecF64x2Le:
2410 c.emit(
2411 newOperationV128Cmp(v128CmpTypeF64x2Le),
2412 )
2413 case wasm.OpcodeVecF64x2Ge:
2414 c.emit(
2415 newOperationV128Cmp(v128CmpTypeF64x2Ge),
2416 )
2417 case wasm.OpcodeVecI8x16Neg:
2418 c.emit(
2419 newOperationV128Neg(shapeI8x16),
2420 )
2421 case wasm.OpcodeVecI16x8Neg:
2422 c.emit(
2423 newOperationV128Neg(shapeI16x8),
2424 )
2425 case wasm.OpcodeVecI32x4Neg:
2426 c.emit(
2427 newOperationV128Neg(shapeI32x4),
2428 )
2429 case wasm.OpcodeVecI64x2Neg:
2430 c.emit(
2431 newOperationV128Neg(shapeI64x2),
2432 )
2433 case wasm.OpcodeVecF32x4Neg:
2434 c.emit(
2435 newOperationV128Neg(shapeF32x4),
2436 )
2437 case wasm.OpcodeVecF64x2Neg:
2438 c.emit(
2439 newOperationV128Neg(shapeF64x2),
2440 )
2441 case wasm.OpcodeVecI8x16Add:
2442 c.emit(
2443 newOperationV128Add(shapeI8x16),
2444 )
2445 case wasm.OpcodeVecI16x8Add:
2446 c.emit(
2447 newOperationV128Add(shapeI16x8),
2448 )
2449 case wasm.OpcodeVecI32x4Add:
2450 c.emit(
2451 newOperationV128Add(shapeI32x4),
2452 )
2453 case wasm.OpcodeVecI64x2Add:
2454 c.emit(
2455 newOperationV128Add(shapeI64x2),
2456 )
2457 case wasm.OpcodeVecF32x4Add:
2458 c.emit(
2459 newOperationV128Add(shapeF32x4),
2460 )
2461 case wasm.OpcodeVecF64x2Add:
2462 c.emit(
2463 newOperationV128Add(shapeF64x2),
2464 )
2465 case wasm.OpcodeVecI8x16Sub:
2466 c.emit(
2467 newOperationV128Sub(shapeI8x16),
2468 )
2469 case wasm.OpcodeVecI16x8Sub:
2470 c.emit(
2471 newOperationV128Sub(shapeI16x8),
2472 )
2473 case wasm.OpcodeVecI32x4Sub:
2474 c.emit(
2475 newOperationV128Sub(shapeI32x4),
2476 )
2477 case wasm.OpcodeVecI64x2Sub:
2478 c.emit(
2479 newOperationV128Sub(shapeI64x2),
2480 )
2481 case wasm.OpcodeVecF32x4Sub:
2482 c.emit(
2483 newOperationV128Sub(shapeF32x4),
2484 )
2485 case wasm.OpcodeVecF64x2Sub:
2486 c.emit(
2487 newOperationV128Sub(shapeF64x2),
2488 )
2489 case wasm.OpcodeVecI8x16AddSatS:
2490 c.emit(
2491 newOperationV128AddSat(shapeI8x16, true),
2492 )
2493 case wasm.OpcodeVecI8x16AddSatU:
2494 c.emit(
2495 newOperationV128AddSat(shapeI8x16, false),
2496 )
2497 case wasm.OpcodeVecI16x8AddSatS:
2498 c.emit(
2499 newOperationV128AddSat(shapeI16x8, true),
2500 )
2501 case wasm.OpcodeVecI16x8AddSatU:
2502 c.emit(
2503 newOperationV128AddSat(shapeI16x8, false),
2504 )
2505 case wasm.OpcodeVecI8x16SubSatS:
2506 c.emit(
2507 newOperationV128SubSat(shapeI8x16, true),
2508 )
2509 case wasm.OpcodeVecI8x16SubSatU:
2510 c.emit(
2511 newOperationV128SubSat(shapeI8x16, false),
2512 )
2513 case wasm.OpcodeVecI16x8SubSatS:
2514 c.emit(
2515 newOperationV128SubSat(shapeI16x8, true),
2516 )
2517 case wasm.OpcodeVecI16x8SubSatU:
2518 c.emit(
2519 newOperationV128SubSat(shapeI16x8, false),
2520 )
2521 case wasm.OpcodeVecI16x8Mul:
2522 c.emit(
2523 newOperationV128Mul(shapeI16x8),
2524 )
2525 case wasm.OpcodeVecI32x4Mul:
2526 c.emit(
2527 newOperationV128Mul(shapeI32x4),
2528 )
2529 case wasm.OpcodeVecI64x2Mul:
2530 c.emit(
2531 newOperationV128Mul(shapeI64x2),
2532 )
2533 case wasm.OpcodeVecF32x4Mul:
2534 c.emit(
2535 newOperationV128Mul(shapeF32x4),
2536 )
2537 case wasm.OpcodeVecF64x2Mul:
2538 c.emit(
2539 newOperationV128Mul(shapeF64x2),
2540 )
2541 case wasm.OpcodeVecF32x4Sqrt:
2542 c.emit(
2543 newOperationV128Sqrt(shapeF32x4),
2544 )
2545 case wasm.OpcodeVecF64x2Sqrt:
2546 c.emit(
2547 newOperationV128Sqrt(shapeF64x2),
2548 )
2549 case wasm.OpcodeVecF32x4Div:
2550 c.emit(
2551 newOperationV128Div(shapeF32x4),
2552 )
2553 case wasm.OpcodeVecF64x2Div:
2554 c.emit(
2555 newOperationV128Div(shapeF64x2),
2556 )
2557 case wasm.OpcodeVecI8x16Abs:
2558 c.emit(
2559 newOperationV128Abs(shapeI8x16),
2560 )
2561 case wasm.OpcodeVecI8x16Popcnt:
2562 c.emit(
2563 newOperationV128Popcnt(shapeI8x16),
2564 )
2565 case wasm.OpcodeVecI16x8Abs:
2566 c.emit(
2567 newOperationV128Abs(shapeI16x8),
2568 )
2569 case wasm.OpcodeVecI32x4Abs:
2570 c.emit(
2571 newOperationV128Abs(shapeI32x4),
2572 )
2573 case wasm.OpcodeVecI64x2Abs:
2574 c.emit(
2575 newOperationV128Abs(shapeI64x2),
2576 )
2577 case wasm.OpcodeVecF32x4Abs:
2578 c.emit(
2579 newOperationV128Abs(shapeF32x4),
2580 )
2581 case wasm.OpcodeVecF64x2Abs:
2582 c.emit(
2583 newOperationV128Abs(shapeF64x2),
2584 )
2585 case wasm.OpcodeVecI8x16MinS:
2586 c.emit(
2587 newOperationV128Min(shapeI8x16, true),
2588 )
2589 case wasm.OpcodeVecI8x16MinU:
2590 c.emit(
2591 newOperationV128Min(shapeI8x16, false),
2592 )
2593 case wasm.OpcodeVecI8x16MaxS:
2594 c.emit(
2595 newOperationV128Max(shapeI8x16, true),
2596 )
2597 case wasm.OpcodeVecI8x16MaxU:
2598 c.emit(
2599 newOperationV128Max(shapeI8x16, false),
2600 )
2601 case wasm.OpcodeVecI8x16AvgrU:
2602 c.emit(
2603 newOperationV128AvgrU(shapeI8x16),
2604 )
2605 case wasm.OpcodeVecI16x8MinS:
2606 c.emit(
2607 newOperationV128Min(shapeI16x8, true),
2608 )
2609 case wasm.OpcodeVecI16x8MinU:
2610 c.emit(
2611 newOperationV128Min(shapeI16x8, false),
2612 )
2613 case wasm.OpcodeVecI16x8MaxS:
2614 c.emit(
2615 newOperationV128Max(shapeI16x8, true),
2616 )
2617 case wasm.OpcodeVecI16x8MaxU:
2618 c.emit(
2619 newOperationV128Max(shapeI16x8, false),
2620 )
2621 case wasm.OpcodeVecI16x8AvgrU:
2622 c.emit(
2623 newOperationV128AvgrU(shapeI16x8),
2624 )
2625 case wasm.OpcodeVecI32x4MinS:
2626 c.emit(
2627 newOperationV128Min(shapeI32x4, true),
2628 )
2629 case wasm.OpcodeVecI32x4MinU:
2630 c.emit(
2631 newOperationV128Min(shapeI32x4, false),
2632 )
2633 case wasm.OpcodeVecI32x4MaxS:
2634 c.emit(
2635 newOperationV128Max(shapeI32x4, true),
2636 )
2637 case wasm.OpcodeVecI32x4MaxU:
2638 c.emit(
2639 newOperationV128Max(shapeI32x4, false),
2640 )
2641 case wasm.OpcodeVecF32x4Min:
2642 c.emit(
2643 newOperationV128Min(shapeF32x4, false),
2644 )
2645 case wasm.OpcodeVecF32x4Max:
2646 c.emit(
2647 newOperationV128Max(shapeF32x4, false),
2648 )
2649 case wasm.OpcodeVecF64x2Min:
2650 c.emit(
2651 newOperationV128Min(shapeF64x2, false),
2652 )
2653 case wasm.OpcodeVecF64x2Max:
2654 c.emit(
2655 newOperationV128Max(shapeF64x2, false),
2656 )
2657 case wasm.OpcodeVecF32x4Pmin:
2658 c.emit(
2659 newOperationV128Pmin(shapeF32x4),
2660 )
2661 case wasm.OpcodeVecF32x4Pmax:
2662 c.emit(
2663 newOperationV128Pmax(shapeF32x4),
2664 )
2665 case wasm.OpcodeVecF64x2Pmin:
2666 c.emit(
2667 newOperationV128Pmin(shapeF64x2),
2668 )
2669 case wasm.OpcodeVecF64x2Pmax:
2670 c.emit(
2671 newOperationV128Pmax(shapeF64x2),
2672 )
2673 case wasm.OpcodeVecF32x4Ceil:
2674 c.emit(
2675 newOperationV128Ceil(shapeF32x4),
2676 )
2677 case wasm.OpcodeVecF32x4Floor:
2678 c.emit(
2679 newOperationV128Floor(shapeF32x4),
2680 )
2681 case wasm.OpcodeVecF32x4Trunc:
2682 c.emit(
2683 newOperationV128Trunc(shapeF32x4),
2684 )
2685 case wasm.OpcodeVecF32x4Nearest:
2686 c.emit(
2687 newOperationV128Nearest(shapeF32x4),
2688 )
2689 case wasm.OpcodeVecF64x2Ceil:
2690 c.emit(
2691 newOperationV128Ceil(shapeF64x2),
2692 )
2693 case wasm.OpcodeVecF64x2Floor:
2694 c.emit(
2695 newOperationV128Floor(shapeF64x2),
2696 )
2697 case wasm.OpcodeVecF64x2Trunc:
2698 c.emit(
2699 newOperationV128Trunc(shapeF64x2),
2700 )
2701 case wasm.OpcodeVecF64x2Nearest:
2702 c.emit(
2703 newOperationV128Nearest(shapeF64x2),
2704 )
2705 case wasm.OpcodeVecI16x8ExtendLowI8x16S:
2706 c.emit(
2707 newOperationV128Extend(shapeI8x16, true, true),
2708 )
2709 case wasm.OpcodeVecI16x8ExtendHighI8x16S:
2710 c.emit(
2711 newOperationV128Extend(shapeI8x16, true, false),
2712 )
2713 case wasm.OpcodeVecI16x8ExtendLowI8x16U:
2714 c.emit(
2715 newOperationV128Extend(shapeI8x16, false, true),
2716 )
2717 case wasm.OpcodeVecI16x8ExtendHighI8x16U:
2718 c.emit(
2719 newOperationV128Extend(shapeI8x16, false, false),
2720 )
2721 case wasm.OpcodeVecI32x4ExtendLowI16x8S:
2722 c.emit(
2723 newOperationV128Extend(shapeI16x8, true, true),
2724 )
2725 case wasm.OpcodeVecI32x4ExtendHighI16x8S:
2726 c.emit(
2727 newOperationV128Extend(shapeI16x8, true, false),
2728 )
2729 case wasm.OpcodeVecI32x4ExtendLowI16x8U:
2730 c.emit(
2731 newOperationV128Extend(shapeI16x8, false, true),
2732 )
2733 case wasm.OpcodeVecI32x4ExtendHighI16x8U:
2734 c.emit(
2735 newOperationV128Extend(shapeI16x8, false, false),
2736 )
2737 case wasm.OpcodeVecI64x2ExtendLowI32x4S:
2738 c.emit(
2739 newOperationV128Extend(shapeI32x4, true, true),
2740 )
2741 case wasm.OpcodeVecI64x2ExtendHighI32x4S:
2742 c.emit(
2743 newOperationV128Extend(shapeI32x4, true, false),
2744 )
2745 case wasm.OpcodeVecI64x2ExtendLowI32x4U:
2746 c.emit(
2747 newOperationV128Extend(shapeI32x4, false, true),
2748 )
2749 case wasm.OpcodeVecI64x2ExtendHighI32x4U:
2750 c.emit(
2751 newOperationV128Extend(shapeI32x4, false, false),
2752 )
2753 case wasm.OpcodeVecI16x8Q15mulrSatS:
2754 c.emit(
2755 newOperationV128Q15mulrSatS(),
2756 )
2757 case wasm.OpcodeVecI16x8ExtMulLowI8x16S:
2758 c.emit(
2759 newOperationV128ExtMul(shapeI8x16, true, true),
2760 )
2761 case wasm.OpcodeVecI16x8ExtMulHighI8x16S:
2762 c.emit(
2763 newOperationV128ExtMul(shapeI8x16, true, false),
2764 )
2765 case wasm.OpcodeVecI16x8ExtMulLowI8x16U:
2766 c.emit(
2767 newOperationV128ExtMul(shapeI8x16, false, true),
2768 )
2769 case wasm.OpcodeVecI16x8ExtMulHighI8x16U:
2770 c.emit(
2771 newOperationV128ExtMul(shapeI8x16, false, false),
2772 )
2773 case wasm.OpcodeVecI32x4ExtMulLowI16x8S:
2774 c.emit(
2775 newOperationV128ExtMul(shapeI16x8, true, true),
2776 )
2777 case wasm.OpcodeVecI32x4ExtMulHighI16x8S:
2778 c.emit(
2779 newOperationV128ExtMul(shapeI16x8, true, false),
2780 )
2781 case wasm.OpcodeVecI32x4ExtMulLowI16x8U:
2782 c.emit(
2783 newOperationV128ExtMul(shapeI16x8, false, true),
2784 )
2785 case wasm.OpcodeVecI32x4ExtMulHighI16x8U:
2786 c.emit(
2787 newOperationV128ExtMul(shapeI16x8, false, false),
2788 )
2789 case wasm.OpcodeVecI64x2ExtMulLowI32x4S:
2790 c.emit(
2791 newOperationV128ExtMul(shapeI32x4, true, true),
2792 )
2793 case wasm.OpcodeVecI64x2ExtMulHighI32x4S:
2794 c.emit(
2795 newOperationV128ExtMul(shapeI32x4, true, false),
2796 )
2797 case wasm.OpcodeVecI64x2ExtMulLowI32x4U:
2798 c.emit(
2799 newOperationV128ExtMul(shapeI32x4, false, true),
2800 )
2801 case wasm.OpcodeVecI64x2ExtMulHighI32x4U:
2802 c.emit(
2803 newOperationV128ExtMul(shapeI32x4, false, false),
2804 )
2805 case wasm.OpcodeVecI16x8ExtaddPairwiseI8x16S:
2806 c.emit(
2807 newOperationV128ExtAddPairwise(shapeI8x16, true),
2808 )
2809 case wasm.OpcodeVecI16x8ExtaddPairwiseI8x16U:
2810 c.emit(
2811 newOperationV128ExtAddPairwise(shapeI8x16, false),
2812 )
2813 case wasm.OpcodeVecI32x4ExtaddPairwiseI16x8S:
2814 c.emit(
2815 newOperationV128ExtAddPairwise(shapeI16x8, true),
2816 )
2817 case wasm.OpcodeVecI32x4ExtaddPairwiseI16x8U:
2818 c.emit(
2819 newOperationV128ExtAddPairwise(shapeI16x8, false),
2820 )
2821 case wasm.OpcodeVecF64x2PromoteLowF32x4Zero:
2822 c.emit(
2823 newOperationV128FloatPromote(),
2824 )
2825 case wasm.OpcodeVecF32x4DemoteF64x2Zero:
2826 c.emit(
2827 newOperationV128FloatDemote(),
2828 )
2829 case wasm.OpcodeVecF32x4ConvertI32x4S:
2830 c.emit(
2831 newOperationV128FConvertFromI(shapeF32x4, true),
2832 )
2833 case wasm.OpcodeVecF32x4ConvertI32x4U:
2834 c.emit(
2835 newOperationV128FConvertFromI(shapeF32x4, false),
2836 )
2837 case wasm.OpcodeVecF64x2ConvertLowI32x4S:
2838 c.emit(
2839 newOperationV128FConvertFromI(shapeF64x2, true),
2840 )
2841 case wasm.OpcodeVecF64x2ConvertLowI32x4U:
2842 c.emit(
2843 newOperationV128FConvertFromI(shapeF64x2, false),
2844 )
2845 case wasm.OpcodeVecI32x4DotI16x8S:
2846 c.emit(
2847 newOperationV128Dot(),
2848 )
2849 case wasm.OpcodeVecI8x16NarrowI16x8S:
2850 c.emit(
2851 newOperationV128Narrow(shapeI16x8, true),
2852 )
2853 case wasm.OpcodeVecI8x16NarrowI16x8U:
2854 c.emit(
2855 newOperationV128Narrow(shapeI16x8, false),
2856 )
2857 case wasm.OpcodeVecI16x8NarrowI32x4S:
2858 c.emit(
2859 newOperationV128Narrow(shapeI32x4, true),
2860 )
2861 case wasm.OpcodeVecI16x8NarrowI32x4U:
2862 c.emit(
2863 newOperationV128Narrow(shapeI32x4, false),
2864 )
2865 case wasm.OpcodeVecI32x4TruncSatF32x4S:
2866 c.emit(
2867 newOperationV128ITruncSatFromF(shapeF32x4, true),
2868 )
2869 case wasm.OpcodeVecI32x4TruncSatF32x4U:
2870 c.emit(
2871 newOperationV128ITruncSatFromF(shapeF32x4, false),
2872 )
2873 case wasm.OpcodeVecI32x4TruncSatF64x2SZero:
2874 c.emit(
2875 newOperationV128ITruncSatFromF(shapeF64x2, true),
2876 )
2877 case wasm.OpcodeVecI32x4TruncSatF64x2UZero:
2878 c.emit(
2879 newOperationV128ITruncSatFromF(shapeF64x2, false),
2880 )
2881 default:
2882 return fmt.Errorf("unsupported vector instruction in interpreterir: %s", wasm.VectorInstructionName(vecOp))
2883 }
2884 case wasm.OpcodeAtomicPrefix:
2885 c.pc++
2886 atomicOp := c.body[c.pc]
2887 switch atomicOp {
2888 case wasm.OpcodeAtomicMemoryWait32:
2889 imm, err := c.readMemoryArg(wasm.OpcodeAtomicMemoryWait32Name)
2890 if err != nil {
2891 return err
2892 }
2893 c.emit(
2894 newOperationAtomicMemoryWait(unsignedTypeI32, imm),
2895 )
2896 case wasm.OpcodeAtomicMemoryWait64:
2897 imm, err := c.readMemoryArg(wasm.OpcodeAtomicMemoryWait64Name)
2898 if err != nil {
2899 return err
2900 }
2901 c.emit(
2902 newOperationAtomicMemoryWait(unsignedTypeI64, imm),
2903 )
2904 case wasm.OpcodeAtomicMemoryNotify:
2905 imm, err := c.readMemoryArg(wasm.OpcodeAtomicMemoryNotifyName)
2906 if err != nil {
2907 return err
2908 }
2909 c.emit(
2910 newOperationAtomicMemoryNotify(imm),
2911 )
2912 case wasm.OpcodeAtomicFence:
2913 // Skip immediate value
2914 c.pc++
2915 _ = c.body[c.pc]
2916 c.emit(
2917 newOperationAtomicFence(),
2918 )
2919 case wasm.OpcodeAtomicI32Load:
2920 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32LoadName)
2921 if err != nil {
2922 return err
2923 }
2924 c.emit(
2925 newOperationAtomicLoad(unsignedTypeI32, imm),
2926 )
2927 case wasm.OpcodeAtomicI64Load:
2928 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64LoadName)
2929 if err != nil {
2930 return err
2931 }
2932 c.emit(
2933 newOperationAtomicLoad(unsignedTypeI64, imm),
2934 )
2935 case wasm.OpcodeAtomicI32Load8U:
2936 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Load8UName)
2937 if err != nil {
2938 return err
2939 }
2940 c.emit(
2941 newOperationAtomicLoad8(unsignedTypeI32, imm),
2942 )
2943 case wasm.OpcodeAtomicI32Load16U:
2944 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Load16UName)
2945 if err != nil {
2946 return err
2947 }
2948 c.emit(
2949 newOperationAtomicLoad16(unsignedTypeI32, imm),
2950 )
2951 case wasm.OpcodeAtomicI64Load8U:
2952 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Load8UName)
2953 if err != nil {
2954 return err
2955 }
2956 c.emit(
2957 newOperationAtomicLoad8(unsignedTypeI64, imm),
2958 )
2959 case wasm.OpcodeAtomicI64Load16U:
2960 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Load16UName)
2961 if err != nil {
2962 return err
2963 }
2964 c.emit(
2965 newOperationAtomicLoad16(unsignedTypeI64, imm),
2966 )
2967 case wasm.OpcodeAtomicI64Load32U:
2968 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Load32UName)
2969 if err != nil {
2970 return err
2971 }
2972 c.emit(
2973 newOperationAtomicLoad(unsignedTypeI32, imm),
2974 )
2975 case wasm.OpcodeAtomicI32Store:
2976 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32StoreName)
2977 if err != nil {
2978 return err
2979 }
2980 c.emit(
2981 newOperationAtomicStore(unsignedTypeI32, imm),
2982 )
2983 case wasm.OpcodeAtomicI32Store8:
2984 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Store8Name)
2985 if err != nil {
2986 return err
2987 }
2988 c.emit(
2989 newOperationAtomicStore8(unsignedTypeI32, imm),
2990 )
2991 case wasm.OpcodeAtomicI32Store16:
2992 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Store16Name)
2993 if err != nil {
2994 return err
2995 }
2996 c.emit(
2997 newOperationAtomicStore16(unsignedTypeI32, imm),
2998 )
2999 case wasm.OpcodeAtomicI64Store:
3000 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64StoreName)
3001 if err != nil {
3002 return err
3003 }
3004 c.emit(
3005 newOperationAtomicStore(unsignedTypeI64, imm),
3006 )
3007 case wasm.OpcodeAtomicI64Store8:
3008 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Store8Name)
3009 if err != nil {
3010 return err
3011 }
3012 c.emit(
3013 newOperationAtomicStore8(unsignedTypeI64, imm),
3014 )
3015 case wasm.OpcodeAtomicI64Store16:
3016 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Store16Name)
3017 if err != nil {
3018 return err
3019 }
3020 c.emit(
3021 newOperationAtomicStore16(unsignedTypeI64, imm),
3022 )
3023 case wasm.OpcodeAtomicI64Store32:
3024 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Store32Name)
3025 if err != nil {
3026 return err
3027 }
3028 c.emit(
3029 newOperationAtomicStore(unsignedTypeI32, imm),
3030 )
3031 case wasm.OpcodeAtomicI32RmwAdd:
3032 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwAddName)
3033 if err != nil {
3034 return err
3035 }
3036 c.emit(
3037 newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpAdd),
3038 )
3039 case wasm.OpcodeAtomicI64RmwAdd:
3040 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwAddName)
3041 if err != nil {
3042 return err
3043 }
3044 c.emit(
3045 newOperationAtomicRMW(unsignedTypeI64, imm, atomicArithmeticOpAdd),
3046 )
3047 case wasm.OpcodeAtomicI32Rmw8AddU:
3048 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8AddUName)
3049 if err != nil {
3050 return err
3051 }
3052 c.emit(
3053 newOperationAtomicRMW8(unsignedTypeI32, imm, atomicArithmeticOpAdd),
3054 )
3055 case wasm.OpcodeAtomicI64Rmw8AddU:
3056 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8AddUName)
3057 if err != nil {
3058 return err
3059 }
3060 c.emit(
3061 newOperationAtomicRMW8(unsignedTypeI64, imm, atomicArithmeticOpAdd),
3062 )
3063 case wasm.OpcodeAtomicI32Rmw16AddU:
3064 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16AddUName)
3065 if err != nil {
3066 return err
3067 }
3068 c.emit(
3069 newOperationAtomicRMW16(unsignedTypeI32, imm, atomicArithmeticOpAdd),
3070 )
3071 case wasm.OpcodeAtomicI64Rmw16AddU:
3072 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16AddUName)
3073 if err != nil {
3074 return err
3075 }
3076 c.emit(
3077 newOperationAtomicRMW16(unsignedTypeI64, imm, atomicArithmeticOpAdd),
3078 )
3079 case wasm.OpcodeAtomicI64Rmw32AddU:
3080 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32AddUName)
3081 if err != nil {
3082 return err
3083 }
3084 c.emit(
3085 newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpAdd),
3086 )
3087 case wasm.OpcodeAtomicI32RmwSub:
3088 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwSubName)
3089 if err != nil {
3090 return err
3091 }
3092 c.emit(
3093 newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpSub),
3094 )
3095 case wasm.OpcodeAtomicI64RmwSub:
3096 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwSubName)
3097 if err != nil {
3098 return err
3099 }
3100 c.emit(
3101 newOperationAtomicRMW(unsignedTypeI64, imm, atomicArithmeticOpSub),
3102 )
3103 case wasm.OpcodeAtomicI32Rmw8SubU:
3104 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8SubUName)
3105 if err != nil {
3106 return err
3107 }
3108 c.emit(
3109 newOperationAtomicRMW8(unsignedTypeI32, imm, atomicArithmeticOpSub),
3110 )
3111 case wasm.OpcodeAtomicI64Rmw8SubU:
3112 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8SubUName)
3113 if err != nil {
3114 return err
3115 }
3116 c.emit(
3117 newOperationAtomicRMW8(unsignedTypeI64, imm, atomicArithmeticOpSub),
3118 )
3119 case wasm.OpcodeAtomicI32Rmw16SubU:
3120 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16SubUName)
3121 if err != nil {
3122 return err
3123 }
3124 c.emit(
3125 newOperationAtomicRMW16(unsignedTypeI32, imm, atomicArithmeticOpSub),
3126 )
3127 case wasm.OpcodeAtomicI64Rmw16SubU:
3128 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16SubUName)
3129 if err != nil {
3130 return err
3131 }
3132 c.emit(
3133 newOperationAtomicRMW16(unsignedTypeI64, imm, atomicArithmeticOpSub),
3134 )
3135 case wasm.OpcodeAtomicI64Rmw32SubU:
3136 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32SubUName)
3137 if err != nil {
3138 return err
3139 }
3140 c.emit(
3141 newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpSub),
3142 )
3143 case wasm.OpcodeAtomicI32RmwAnd:
3144 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwAndName)
3145 if err != nil {
3146 return err
3147 }
3148 c.emit(
3149 newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpAnd),
3150 )
3151 case wasm.OpcodeAtomicI64RmwAnd:
3152 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwAndName)
3153 if err != nil {
3154 return err
3155 }
3156 c.emit(
3157 newOperationAtomicRMW(unsignedTypeI64, imm, atomicArithmeticOpAnd),
3158 )
3159 case wasm.OpcodeAtomicI32Rmw8AndU:
3160 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8AndUName)
3161 if err != nil {
3162 return err
3163 }
3164 c.emit(
3165 newOperationAtomicRMW8(unsignedTypeI32, imm, atomicArithmeticOpAnd),
3166 )
3167 case wasm.OpcodeAtomicI64Rmw8AndU:
3168 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8AndUName)
3169 if err != nil {
3170 return err
3171 }
3172 c.emit(
3173 newOperationAtomicRMW8(unsignedTypeI64, imm, atomicArithmeticOpAnd),
3174 )
3175 case wasm.OpcodeAtomicI32Rmw16AndU:
3176 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16AndUName)
3177 if err != nil {
3178 return err
3179 }
3180 c.emit(
3181 newOperationAtomicRMW16(unsignedTypeI32, imm, atomicArithmeticOpAnd),
3182 )
3183 case wasm.OpcodeAtomicI64Rmw16AndU:
3184 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16AndUName)
3185 if err != nil {
3186 return err
3187 }
3188 c.emit(
3189 newOperationAtomicRMW16(unsignedTypeI64, imm, atomicArithmeticOpAnd),
3190 )
3191 case wasm.OpcodeAtomicI64Rmw32AndU:
3192 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32AndUName)
3193 if err != nil {
3194 return err
3195 }
3196 c.emit(
3197 newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpAnd),
3198 )
3199 case wasm.OpcodeAtomicI32RmwOr:
3200 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwOrName)
3201 if err != nil {
3202 return err
3203 }
3204 c.emit(
3205 newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpOr),
3206 )
3207 case wasm.OpcodeAtomicI64RmwOr:
3208 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwOrName)
3209 if err != nil {
3210 return err
3211 }
3212 c.emit(
3213 newOperationAtomicRMW(unsignedTypeI64, imm, atomicArithmeticOpOr),
3214 )
3215 case wasm.OpcodeAtomicI32Rmw8OrU:
3216 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8OrUName)
3217 if err != nil {
3218 return err
3219 }
3220 c.emit(
3221 newOperationAtomicRMW8(unsignedTypeI32, imm, atomicArithmeticOpOr),
3222 )
3223 case wasm.OpcodeAtomicI64Rmw8OrU:
3224 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8OrUName)
3225 if err != nil {
3226 return err
3227 }
3228 c.emit(
3229 newOperationAtomicRMW8(unsignedTypeI64, imm, atomicArithmeticOpOr),
3230 )
3231 case wasm.OpcodeAtomicI32Rmw16OrU:
3232 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16OrUName)
3233 if err != nil {
3234 return err
3235 }
3236 c.emit(
3237 newOperationAtomicRMW16(unsignedTypeI32, imm, atomicArithmeticOpOr),
3238 )
3239 case wasm.OpcodeAtomicI64Rmw16OrU:
3240 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16OrUName)
3241 if err != nil {
3242 return err
3243 }
3244 c.emit(
3245 newOperationAtomicRMW16(unsignedTypeI64, imm, atomicArithmeticOpOr),
3246 )
3247 case wasm.OpcodeAtomicI64Rmw32OrU:
3248 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32OrUName)
3249 if err != nil {
3250 return err
3251 }
3252 c.emit(
3253 newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpOr),
3254 )
3255 case wasm.OpcodeAtomicI32RmwXor:
3256 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwXorName)
3257 if err != nil {
3258 return err
3259 }
3260 c.emit(
3261 newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpXor),
3262 )
3263 case wasm.OpcodeAtomicI64RmwXor:
3264 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwXorName)
3265 if err != nil {
3266 return err
3267 }
3268 c.emit(
3269 newOperationAtomicRMW(unsignedTypeI64, imm, atomicArithmeticOpXor),
3270 )
3271 case wasm.OpcodeAtomicI32Rmw8XorU:
3272 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8XorUName)
3273 if err != nil {
3274 return err
3275 }
3276 c.emit(
3277 newOperationAtomicRMW8(unsignedTypeI32, imm, atomicArithmeticOpXor),
3278 )
3279 case wasm.OpcodeAtomicI64Rmw8XorU:
3280 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8XorUName)
3281 if err != nil {
3282 return err
3283 }
3284 c.emit(
3285 newOperationAtomicRMW8(unsignedTypeI64, imm, atomicArithmeticOpXor),
3286 )
3287 case wasm.OpcodeAtomicI32Rmw16XorU:
3288 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16XorUName)
3289 if err != nil {
3290 return err
3291 }
3292 c.emit(
3293 newOperationAtomicRMW16(unsignedTypeI32, imm, atomicArithmeticOpXor),
3294 )
3295 case wasm.OpcodeAtomicI64Rmw16XorU:
3296 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16XorUName)
3297 if err != nil {
3298 return err
3299 }
3300 c.emit(
3301 newOperationAtomicRMW16(unsignedTypeI64, imm, atomicArithmeticOpXor),
3302 )
3303 case wasm.OpcodeAtomicI64Rmw32XorU:
3304 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32XorUName)
3305 if err != nil {
3306 return err
3307 }
3308 c.emit(
3309 newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpXor),
3310 )
3311 case wasm.OpcodeAtomicI32RmwXchg:
3312 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwXchgName)
3313 if err != nil {
3314 return err
3315 }
3316 c.emit(
3317 newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpNop),
3318 )
3319 case wasm.OpcodeAtomicI64RmwXchg:
3320 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwXchgName)
3321 if err != nil {
3322 return err
3323 }
3324 c.emit(
3325 newOperationAtomicRMW(unsignedTypeI64, imm, atomicArithmeticOpNop),
3326 )
3327 case wasm.OpcodeAtomicI32Rmw8XchgU:
3328 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8XchgUName)
3329 if err != nil {
3330 return err
3331 }
3332 c.emit(
3333 newOperationAtomicRMW8(unsignedTypeI32, imm, atomicArithmeticOpNop),
3334 )
3335 case wasm.OpcodeAtomicI64Rmw8XchgU:
3336 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8XchgUName)
3337 if err != nil {
3338 return err
3339 }
3340 c.emit(
3341 newOperationAtomicRMW8(unsignedTypeI64, imm, atomicArithmeticOpNop),
3342 )
3343 case wasm.OpcodeAtomicI32Rmw16XchgU:
3344 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16XchgUName)
3345 if err != nil {
3346 return err
3347 }
3348 c.emit(
3349 newOperationAtomicRMW16(unsignedTypeI32, imm, atomicArithmeticOpNop),
3350 )
3351 case wasm.OpcodeAtomicI64Rmw16XchgU:
3352 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16XchgUName)
3353 if err != nil {
3354 return err
3355 }
3356 c.emit(
3357 newOperationAtomicRMW16(unsignedTypeI64, imm, atomicArithmeticOpNop),
3358 )
3359 case wasm.OpcodeAtomicI64Rmw32XchgU:
3360 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32XchgUName)
3361 if err != nil {
3362 return err
3363 }
3364 c.emit(
3365 newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpNop),
3366 )
3367 case wasm.OpcodeAtomicI32RmwCmpxchg:
3368 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwCmpxchgName)
3369 if err != nil {
3370 return err
3371 }
3372 c.emit(
3373 newOperationAtomicRMWCmpxchg(unsignedTypeI32, imm),
3374 )
3375 case wasm.OpcodeAtomicI64RmwCmpxchg:
3376 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwCmpxchgName)
3377 if err != nil {
3378 return err
3379 }
3380 c.emit(
3381 newOperationAtomicRMWCmpxchg(unsignedTypeI64, imm),
3382 )
3383 case wasm.OpcodeAtomicI32Rmw8CmpxchgU:
3384 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8CmpxchgUName)
3385 if err != nil {
3386 return err
3387 }
3388 c.emit(
3389 newOperationAtomicRMW8Cmpxchg(unsignedTypeI32, imm),
3390 )
3391 case wasm.OpcodeAtomicI64Rmw8CmpxchgU:
3392 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8CmpxchgUName)
3393 if err != nil {
3394 return err
3395 }
3396 c.emit(
3397 newOperationAtomicRMW8Cmpxchg(unsignedTypeI64, imm),
3398 )
3399 case wasm.OpcodeAtomicI32Rmw16CmpxchgU:
3400 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16CmpxchgUName)
3401 if err != nil {
3402 return err
3403 }
3404 c.emit(
3405 newOperationAtomicRMW16Cmpxchg(unsignedTypeI32, imm),
3406 )
3407 case wasm.OpcodeAtomicI64Rmw16CmpxchgU:
3408 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16CmpxchgUName)
3409 if err != nil {
3410 return err
3411 }
3412 c.emit(
3413 newOperationAtomicRMW16Cmpxchg(unsignedTypeI64, imm),
3414 )
3415 case wasm.OpcodeAtomicI64Rmw32CmpxchgU:
3416 imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32CmpxchgUName)
3417 if err != nil {
3418 return err
3419 }
3420 c.emit(
3421 newOperationAtomicRMWCmpxchg(unsignedTypeI32, imm),
3422 )
3423 default:
3424 return fmt.Errorf("unsupported atomic instruction in interpreterir: %s", wasm.AtomicInstructionName(atomicOp))
3425 }
3426 default:
3427 return fmt.Errorf("unsupported instruction in interpreterir: 0x%x", op)
3428 }
3429
3430 // Move the program counter to point to the next instruction.
3431 c.pc++
3432 return nil
3433}
3434
3435func (c *compiler) nextFrameID() (id uint32) {
3436 id = c.currentFrameID + 1
3437 c.currentFrameID++
3438 return
3439}
3440
3441func (c *compiler) applyToStack(opcode wasm.Opcode) (index uint32, err error) {
3442 switch opcode {
3443 case
3444 // These are the opcodes that is coupled with "index" immediate
3445 // and it DOES affect the signature of opcode.
3446 wasm.OpcodeCall,
3447 wasm.OpcodeCallIndirect,
3448 wasm.OpcodeLocalGet,
3449 wasm.OpcodeLocalSet,
3450 wasm.OpcodeLocalTee,
3451 wasm.OpcodeGlobalGet,
3452 wasm.OpcodeGlobalSet:
3453 // Assumes that we are at the opcode now so skip it before read immediates.
3454 v, num, err := leb128.LoadUint32(c.body[c.pc+1:])
3455 if err != nil {
3456 return 0, fmt.Errorf("reading immediates: %w", err)
3457 }
3458 c.pc += num
3459 index = v
3460 default:
3461 // Note that other opcodes are free of index
3462 // as it doesn't affect the signature of opt code.
3463 // In other words, the "index" argument of wasmOpcodeSignature
3464 // is ignored there.
3465 }
3466
3467 if c.unreachableState.on {
3468 return 0, nil
3469 }
3470
3471 // Retrieve the signature of the opcode.
3472 s, err := c.wasmOpcodeSignature(opcode, index)
3473 if err != nil {
3474 return 0, err
3475 }
3476
3477 // Manipulate the stack according to the signature.
3478 // Note that the following algorithm assumes that
3479 // the unknown type is unique in the signature,
3480 // and is determined by the actual type on the stack.
3481 // The determined type is stored in this typeParam.
3482 var typeParam unsignedType
3483 var typeParamFound bool
3484 for i := range s.in {
3485 want := s.in[len(s.in)-1-i]
3486 actual := c.stackPop()
3487 if want == unsignedTypeUnknown && typeParamFound {
3488 want = typeParam
3489 } else if want == unsignedTypeUnknown {
3490 want = actual
3491 typeParam = want
3492 typeParamFound = true
3493 }
3494 if want != actual {
3495 return 0, fmt.Errorf("input signature mismatch: want %s but have %s", want, actual)
3496 }
3497 }
3498
3499 for _, target := range s.out {
3500 if target == unsignedTypeUnknown && !typeParamFound {
3501 return 0, fmt.Errorf("cannot determine type of unknown result")
3502 } else if target == unsignedTypeUnknown {
3503 c.stackPush(typeParam)
3504 } else {
3505 c.stackPush(target)
3506 }
3507 }
3508
3509 return index, nil
3510}
3511
3512func (c *compiler) stackPeek() (ret unsignedType) {
3513 ret = c.stack[len(c.stack)-1]
3514 return
3515}
3516
3517func (c *compiler) stackSwitchAt(frame *controlFrame) {
3518 c.stack = c.stack[:frame.originalStackLenWithoutParam]
3519 c.stackLenInUint64 = frame.originalStackLenWithoutParamUint64
3520}
3521
3522func (c *compiler) stackPop() (ret unsignedType) {
3523 // No need to check stack bound
3524 // as we can assume that all the operations
3525 // are valid thanks to validateFunction
3526 // at module validation phase.
3527 ret = c.stack[len(c.stack)-1]
3528 c.stack = c.stack[:len(c.stack)-1]
3529 c.stackLenInUint64 -= 1 + int(unsignedTypeV128&ret>>2)
3530 return
3531}
3532
3533func (c *compiler) stackPush(ts unsignedType) {
3534 c.stack = append(c.stack, ts)
3535 c.stackLenInUint64 += 1 + int(unsignedTypeV128&ts>>2)
3536}
3537
3538// emit adds the operations into the result.
3539func (c *compiler) emit(op unionOperation) {
3540 if !c.unreachableState.on {
3541 switch op.Kind {
3542 case operationKindDrop:
3543 // If the drop range is nil,
3544 // we could remove such operations.
3545 // That happens when drop operation is unnecessary.
3546 // i.e. when there's no need to adjust stack before jmp.
3547 if int64(op.U1) == -1 {
3548 return
3549 }
3550 }
3551 c.result.Operations = append(c.result.Operations, op)
3552 if c.needSourceOffset {
3553 c.result.IROperationSourceOffsetsInWasmBinary = append(c.result.IROperationSourceOffsetsInWasmBinary,
3554 c.currentOpPC+c.bodyOffsetInCodeSection)
3555 }
3556 }
3557}
3558
3559// Emit const expression with default values of the given type.
3560func (c *compiler) emitDefaultValue(t wasm.ValueType) {
3561 switch t {
3562 case wasm.ValueTypeI32:
3563 c.stackPush(unsignedTypeI32)
3564 c.emit(newOperationConstI32(0))
3565 case wasm.ValueTypeI64, wasm.ValueTypeExternref, wasm.ValueTypeFuncref:
3566 c.stackPush(unsignedTypeI64)
3567 c.emit(newOperationConstI64(0))
3568 case wasm.ValueTypeF32:
3569 c.stackPush(unsignedTypeF32)
3570 c.emit(newOperationConstF32(0))
3571 case wasm.ValueTypeF64:
3572 c.stackPush(unsignedTypeF64)
3573 c.emit(newOperationConstF64(0))
3574 case wasm.ValueTypeV128:
3575 c.stackPush(unsignedTypeV128)
3576 c.emit(newOperationV128Const(0, 0))
3577 }
3578}
3579
3580// Returns the "depth" (starting from top of the stack)
3581// of the n-th local.
3582func (c *compiler) localDepth(index wasm.Index) int {
3583 height := c.localIndexToStackHeightInUint64[index]
3584 return c.stackLenInUint64 - 1 - height
3585}
3586
3587func (c *compiler) localType(index wasm.Index) (t wasm.ValueType) {
3588 if params := uint32(len(c.sig.Params)); index < params {
3589 t = c.sig.Params[index]
3590 } else {
3591 t = c.localTypes[index-params]
3592 }
3593 return
3594}
3595
3596// getFrameDropRange returns the range (starting from top of the stack) that spans across the (uint64) stack. The range is
3597// supposed to be dropped from the stack when the given frame exists or branch into it.
3598//
3599// * frame is the control frame which the call-site is trying to branch into or exit.
3600// * isEnd true if the call-site is handling wasm.OpcodeEnd.
3601func (c *compiler) getFrameDropRange(frame *controlFrame, isEnd bool) inclusiveRange {
3602 var start int
3603 if !isEnd && frame.kind == controlFrameKindLoop {
3604 // If this is not End and the call-site is trying to branch into the Loop control frame,
3605 // we have to Start executing from the beginning of the loop block.
3606 // Therefore, we have to pass the inputs to the frame.
3607 start = frame.blockType.ParamNumInUint64
3608 } else {
3609 start = frame.blockType.ResultNumInUint64
3610 }
3611 end := c.stackLenInUint64 - 1 - frame.originalStackLenWithoutParamUint64
3612 if start <= end {
3613 return inclusiveRange{Start: int32(start), End: int32(end)}
3614 } else {
3615 return nopinclusiveRange
3616 }
3617}
3618
3619func (c *compiler) readMemoryArg(tag string) (memoryArg, error) {
3620 c.result.UsesMemory = true
3621 alignment, num, err := leb128.LoadUint32(c.body[c.pc+1:])
3622 if err != nil {
3623 return memoryArg{}, fmt.Errorf("reading alignment for %s: %w", tag, err)
3624 }
3625 c.pc += num
3626 offset, num, err := leb128.LoadUint32(c.body[c.pc+1:])
3627 if err != nil {
3628 return memoryArg{}, fmt.Errorf("reading offset for %s: %w", tag, err)
3629 }
3630 c.pc += num
3631 return memoryArg{Offset: offset, Alignment: alignment}, nil
3632}