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