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