github.com/tetratelabs/wazero@v1.2.1/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/tetratelabs/wazero/api" 11 "github.com/tetratelabs/wazero/internal/leb128" 12 "github.com/tetratelabs/wazero/internal/wasm" 13 ) 14 15 type controlFrameKind byte 16 17 const ( 18 controlFrameKindBlockWithContinuationLabel controlFrameKind = iota 19 controlFrameKindBlockWithoutContinuationLabel 20 controlFrameKindFunction 21 controlFrameKindLoop 22 controlFrameKindIfWithElse 23 controlFrameKindIfWithoutElse 24 ) 25 26 type ( 27 controlFrame struct { 28 frameID uint32 29 // originalStackLen holds the number of values on the stack 30 // when Start executing this control frame minus params for the block. 31 originalStackLenWithoutParam int 32 blockType *wasm.FunctionType 33 kind controlFrameKind 34 } 35 controlFrames struct{ frames []controlFrame } 36 ) 37 38 func (c *controlFrame) ensureContinuation() { 39 // Make sure that if the frame is block and doesn't have continuation, 40 // change the Kind so we can emit the continuation block 41 // later when we reach the End instruction of this frame. 42 if c.kind == controlFrameKindBlockWithoutContinuationLabel { 43 c.kind = controlFrameKindBlockWithContinuationLabel 44 } 45 } 46 47 func (c *controlFrame) asLabel() Label { 48 switch c.kind { 49 case controlFrameKindBlockWithContinuationLabel, 50 controlFrameKindBlockWithoutContinuationLabel: 51 return NewLabel(LabelKindContinuation, c.frameID) 52 case controlFrameKindLoop: 53 return NewLabel(LabelKindHeader, c.frameID) 54 case controlFrameKindFunction: 55 return NewLabel(LabelKindReturn, 0) 56 case controlFrameKindIfWithElse, 57 controlFrameKindIfWithoutElse: 58 return NewLabel(LabelKindContinuation, c.frameID) 59 } 60 panic(fmt.Sprintf("unreachable: a bug in 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 { 383 instName = wasm.InstructionName(op) 384 } 385 fmt.Printf("handling %s, unreachable_state(on=%v,depth=%d), stack=%v\n", 386 instName, c.unreachableState.on, c.unreachableState.depth, c.stack, 387 ) 388 } 389 390 var peekValueType UnsignedType 391 if len(c.stack) > 0 { 392 peekValueType = c.stackPeek() 393 } 394 395 // Modify the stack according the current instruction. 396 // Note that some instructions will read "index" in 397 // applyToStack and advance c.pc inside the function. 398 index, err := c.applyToStack(op) 399 if err != nil { 400 return fmt.Errorf("apply stack failed for %s: %w", wasm.InstructionName(op), err) 401 } 402 // Now we handle each instruction, and 403 // emit the corresponding wazeroir operations to the results. 404 operatorSwitch: 405 switch op { 406 case wasm.OpcodeUnreachable: 407 c.emit(NewOperationUnreachable()) 408 c.markUnreachable() 409 case wasm.OpcodeNop: 410 // Nop is noop! 411 case wasm.OpcodeBlock: 412 c.br.Reset(c.body[c.pc+1:]) 413 bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures) 414 if err != nil { 415 return fmt.Errorf("reading block type for block instruction: %w", err) 416 } 417 c.pc += num 418 419 if c.unreachableState.on { 420 // If it is currently in unreachable, 421 // just remove the entire block. 422 c.unreachableState.depth++ 423 break operatorSwitch 424 } 425 426 // Create a new frame -- entering this block. 427 frame := controlFrame{ 428 frameID: c.nextFrameID(), 429 originalStackLenWithoutParam: len(c.stack) - len(bt.Params), 430 kind: controlFrameKindBlockWithoutContinuationLabel, 431 blockType: bt, 432 } 433 c.controlFrames.push(frame) 434 435 case wasm.OpcodeLoop: 436 c.br.Reset(c.body[c.pc+1:]) 437 bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures) 438 if err != nil { 439 return fmt.Errorf("reading block type for loop instruction: %w", err) 440 } 441 c.pc += num 442 443 if c.unreachableState.on { 444 // If it is currently in unreachable, 445 // just remove the entire block. 446 c.unreachableState.depth++ 447 break operatorSwitch 448 } 449 450 // Create a new frame -- entering loop. 451 frame := controlFrame{ 452 frameID: c.nextFrameID(), 453 originalStackLenWithoutParam: len(c.stack) - len(bt.Params), 454 kind: controlFrameKindLoop, 455 blockType: bt, 456 } 457 c.controlFrames.push(frame) 458 459 // Prep labels for inside and the continuation of this loop. 460 loopLabel := NewLabel(LabelKindHeader, frame.frameID) 461 c.result.LabelCallers[loopLabel]++ 462 463 // Emit the branch operation to enter inside the loop. 464 c.emit(NewOperationBr(loopLabel)) 465 c.emit(NewOperationLabel(loopLabel)) 466 467 // Insert the exit code check on the loop header, which is the only necessary point in the function body 468 // to prevent infinite loop. 469 // 470 // Note that this is a little aggressive: this checks the exit code regardless the loop header is actually 471 // the loop. In other words, this checks even when no br/br_if/br_table instructions jumping to this loop 472 // exist. However, in reality, that shouldn't be an issue since such "noop" loop header will highly likely be 473 // optimized out by almost all guest language compilers which have the control flow optimization passes. 474 if c.ensureTermination { 475 c.emit(NewOperationBuiltinFunctionCheckExitCode()) 476 } 477 case wasm.OpcodeIf: 478 c.br.Reset(c.body[c.pc+1:]) 479 bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures) 480 if err != nil { 481 return fmt.Errorf("reading block type for if instruction: %w", err) 482 } 483 c.pc += num 484 485 if c.unreachableState.on { 486 // If it is currently in unreachable, 487 // just remove the entire block. 488 c.unreachableState.depth++ 489 break operatorSwitch 490 } 491 492 // Create a new frame -- entering if. 493 frame := controlFrame{ 494 frameID: c.nextFrameID(), 495 originalStackLenWithoutParam: len(c.stack) - len(bt.Params), 496 // Note this will be set to controlFrameKindIfWithElse 497 // when else opcode found later. 498 kind: controlFrameKindIfWithoutElse, 499 blockType: bt, 500 } 501 c.controlFrames.push(frame) 502 503 // Prep labels for if and else of this if. 504 thenLabel := NewLabel(LabelKindHeader, frame.frameID) 505 elseLabel := NewLabel(LabelKindElse, frame.frameID) 506 c.result.LabelCallers[thenLabel]++ 507 c.result.LabelCallers[elseLabel]++ 508 509 // Emit the branch operation to enter the then block. 510 c.emit(NewOperationBrIf(thenLabel, elseLabel, NopInclusiveRange)) 511 c.emit(NewOperationLabel(thenLabel)) 512 case wasm.OpcodeElse: 513 frame := c.controlFrames.top() 514 if c.unreachableState.on && c.unreachableState.depth > 0 { 515 // If it is currently in unreachable, and the nested if, 516 // just remove the entire else block. 517 break operatorSwitch 518 } else if c.unreachableState.on { 519 // If it is currently in unreachable, and the non-nested if, 520 // reset the stack so we can correctly handle the else block. 521 top := c.controlFrames.top() 522 c.stack = c.stack[:top.originalStackLenWithoutParam] 523 top.kind = controlFrameKindIfWithElse 524 525 // Re-push the parameters to the if block so that else block can use them. 526 for _, t := range frame.blockType.Params { 527 c.stackPush(wasmValueTypeToUnsignedType(t)) 528 } 529 530 // We are no longer unreachable in else frame, 531 // so emit the correct label, and reset the unreachable state. 532 elseLabel := NewLabel(LabelKindElse, frame.frameID) 533 c.resetUnreachable() 534 c.emit( 535 NewOperationLabel(elseLabel), 536 ) 537 break operatorSwitch 538 } 539 540 // Change the Kind of this If block, indicating that 541 // the if has else block. 542 frame.kind = controlFrameKindIfWithElse 543 544 // We need to reset the stack so that 545 // the values pushed inside the then block 546 // do not affect the else block. 547 dropOp := NewOperationDrop(c.getFrameDropRange(frame, false)) 548 549 // Reset the stack manipulated by the then block, and re-push the block param types to the stack. 550 551 c.stack = c.stack[:frame.originalStackLenWithoutParam] 552 for _, t := range frame.blockType.Params { 553 c.stackPush(wasmValueTypeToUnsignedType(t)) 554 } 555 556 // Prep labels for else and the continuation of this if block. 557 elseLabel := NewLabel(LabelKindElse, frame.frameID) 558 continuationLabel := NewLabel(LabelKindContinuation, frame.frameID) 559 c.result.LabelCallers[continuationLabel]++ 560 561 // Emit the instructions for exiting the if loop, 562 // and then the initiation of else block. 563 c.emit(dropOp) 564 // Jump to the continuation of this block. 565 c.emit(NewOperationBr(continuationLabel)) 566 // Initiate the else block. 567 c.emit(NewOperationLabel(elseLabel)) 568 case wasm.OpcodeEnd: 569 if c.unreachableState.on && c.unreachableState.depth > 0 { 570 c.unreachableState.depth-- 571 break operatorSwitch 572 } else if c.unreachableState.on { 573 c.resetUnreachable() 574 575 frame := c.controlFrames.pop() 576 if c.controlFrames.empty() { 577 return nil 578 } 579 580 c.stack = c.stack[:frame.originalStackLenWithoutParam] 581 for _, t := range frame.blockType.Results { 582 c.stackPush(wasmValueTypeToUnsignedType(t)) 583 } 584 585 continuationLabel := NewLabel(LabelKindContinuation, frame.frameID) 586 if frame.kind == controlFrameKindIfWithoutElse { 587 // Emit the else label. 588 elseLabel := NewLabel(LabelKindElse, frame.frameID) 589 c.result.LabelCallers[continuationLabel]++ 590 c.emit(NewOperationLabel(elseLabel)) 591 c.emit(NewOperationBr(continuationLabel)) 592 c.emit(NewOperationLabel(continuationLabel)) 593 } else { 594 c.emit( 595 NewOperationLabel(continuationLabel), 596 ) 597 } 598 599 break operatorSwitch 600 } 601 602 frame := c.controlFrames.pop() 603 604 // We need to reset the stack so that 605 // the values pushed inside the block. 606 dropOp := NewOperationDrop(c.getFrameDropRange(frame, true)) 607 c.stack = c.stack[:frame.originalStackLenWithoutParam] 608 609 // Push the result types onto the stack. 610 for _, t := range frame.blockType.Results { 611 c.stackPush(wasmValueTypeToUnsignedType(t)) 612 } 613 614 // Emit the instructions according to the Kind of the current control frame. 615 switch frame.kind { 616 case controlFrameKindFunction: 617 if !c.controlFrames.empty() { 618 // Should never happen. If so, there's a bug in the translation. 619 panic("bug: found more function control frames") 620 } 621 // Return from function. 622 c.emit(dropOp) 623 c.emit(NewOperationBr(NewLabel(LabelKindReturn, 0))) 624 case controlFrameKindIfWithoutElse: 625 // This case we have to emit "empty" else label. 626 elseLabel := NewLabel(LabelKindElse, frame.frameID) 627 continuationLabel := NewLabel(LabelKindContinuation, frame.frameID) 628 c.result.LabelCallers[continuationLabel] += 2 629 c.emit(dropOp) 630 c.emit(NewOperationBr(continuationLabel)) 631 // Emit the else which soon branches into the continuation. 632 c.emit(NewOperationLabel(elseLabel)) 633 c.emit(NewOperationBr(continuationLabel)) 634 // Initiate the continuation. 635 c.emit(NewOperationLabel(continuationLabel)) 636 case controlFrameKindBlockWithContinuationLabel, 637 controlFrameKindIfWithElse: 638 continuationLabel := NewLabel(LabelKindContinuation, frame.frameID) 639 c.result.LabelCallers[continuationLabel]++ 640 c.emit(dropOp) 641 c.emit(NewOperationBr(continuationLabel)) 642 c.emit(NewOperationLabel(continuationLabel)) 643 case controlFrameKindLoop, controlFrameKindBlockWithoutContinuationLabel: 644 c.emit( 645 dropOp, 646 ) 647 default: 648 // Should never happen. If so, there's a bug in the translation. 649 panic(fmt.Errorf("bug: invalid control frame Kind: 0x%x", frame.kind)) 650 } 651 652 case wasm.OpcodeBr: 653 targetIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:]) 654 if err != nil { 655 return fmt.Errorf("read the target for br_if: %w", err) 656 } 657 c.pc += n 658 659 if c.unreachableState.on { 660 // If it is currently in unreachable, br is no-op. 661 break operatorSwitch 662 } 663 664 targetFrame := c.controlFrames.get(int(targetIndex)) 665 targetFrame.ensureContinuation() 666 dropOp := NewOperationDrop(c.getFrameDropRange(targetFrame, false)) 667 targetID := targetFrame.asLabel() 668 c.result.LabelCallers[targetID]++ 669 c.emit(dropOp) 670 c.emit(NewOperationBr(targetID)) 671 // Br operation is stack-polymorphic, and mark the state as unreachable. 672 // That means subsequent instructions in the current control frame are "unreachable" 673 // and can be safely removed. 674 c.markUnreachable() 675 case wasm.OpcodeBrIf: 676 targetIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:]) 677 if err != nil { 678 return fmt.Errorf("read the target for br_if: %w", err) 679 } 680 c.pc += n 681 682 if c.unreachableState.on { 683 // If it is currently in unreachable, br-if is no-op. 684 break operatorSwitch 685 } 686 687 targetFrame := c.controlFrames.get(int(targetIndex)) 688 targetFrame.ensureContinuation() 689 drop := c.getFrameDropRange(targetFrame, false) 690 target := targetFrame.asLabel() 691 c.result.LabelCallers[target]++ 692 693 continuationLabel := NewLabel(LabelKindHeader, c.nextFrameID()) 694 c.result.LabelCallers[continuationLabel]++ 695 c.emit(NewOperationBrIf(target, continuationLabel, drop)) 696 // Start emitting else block operations. 697 c.emit(NewOperationLabel(continuationLabel)) 698 case wasm.OpcodeBrTable: 699 c.br.Reset(c.body[c.pc+1:]) 700 r := c.br 701 numTargets, n, err := leb128.DecodeUint32(r) 702 if err != nil { 703 return fmt.Errorf("error reading number of targets in br_table: %w", err) 704 } 705 c.pc += n 706 707 if c.unreachableState.on { 708 // If it is currently in unreachable, br_table is no-op. 709 // But before proceeding to the next instruction, we must advance the pc 710 // according to the number of br_table targets. 711 for i := uint32(0); i <= numTargets; i++ { // inclusive as we also need to read the index of default target. 712 _, n, err := leb128.DecodeUint32(r) 713 if err != nil { 714 return fmt.Errorf("error reading target %d in br_table: %w", i, err) 715 } 716 c.pc += n 717 } 718 break operatorSwitch 719 } 720 721 // Read the branch targets. 722 s := numTargets * 2 723 targetLabels := make([]uint64, 2+s) // (label, InclusiveRange) * (default+numTargets) 724 for i := uint32(0); i < s; i += 2 { 725 l, n, err := leb128.DecodeUint32(r) 726 if err != nil { 727 return fmt.Errorf("error reading target %d in br_table: %w", i, err) 728 } 729 c.pc += n 730 targetFrame := c.controlFrames.get(int(l)) 731 targetFrame.ensureContinuation() 732 drop := c.getFrameDropRange(targetFrame, false) 733 targetLabel := targetFrame.asLabel() 734 targetLabels[i] = uint64(targetLabel) 735 targetLabels[i+1] = drop.AsU64() 736 c.result.LabelCallers[targetLabel]++ 737 } 738 739 // Prep default target control frame. 740 l, n, err := leb128.DecodeUint32(r) 741 if err != nil { 742 return fmt.Errorf("error reading default target of br_table: %w", err) 743 } 744 c.pc += n 745 defaultTargetFrame := c.controlFrames.get(int(l)) 746 defaultTargetFrame.ensureContinuation() 747 defaultTargetDrop := c.getFrameDropRange(defaultTargetFrame, false) 748 defaultLabel := defaultTargetFrame.asLabel() 749 c.result.LabelCallers[defaultLabel]++ 750 targetLabels[s] = uint64(defaultLabel) 751 targetLabels[s+1] = defaultTargetDrop.AsU64() 752 c.emit(NewOperationBrTable(targetLabels)) 753 754 // br_table operation is stack-polymorphic, and mark the state as unreachable. 755 // That means subsequent instructions in the current control frame are "unreachable" 756 // and can be safely removed. 757 c.markUnreachable() 758 case wasm.OpcodeReturn: 759 functionFrame := c.controlFrames.functionFrame() 760 dropOp := NewOperationDrop(c.getFrameDropRange(functionFrame, false)) 761 762 // Cleanup the stack and then jmp to function frame's continuation (meaning return). 763 c.emit(dropOp) 764 c.emit(NewOperationBr(functionFrame.asLabel())) 765 766 // Return operation is stack-polymorphic, and mark the state as unreachable. 767 // That means subsequent instructions in the current control frame are "unreachable" 768 // and can be safely removed. 769 c.markUnreachable() 770 case wasm.OpcodeCall: 771 c.emit( 772 NewOperationCall(index), 773 ) 774 case wasm.OpcodeCallIndirect: 775 typeIndex := index 776 tableIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:]) 777 if err != nil { 778 return fmt.Errorf("read target for br_table: %w", err) 779 } 780 c.pc += n 781 c.emit( 782 NewOperationCallIndirect(typeIndex, tableIndex), 783 ) 784 case wasm.OpcodeDrop: 785 r := InclusiveRange{Start: 0, End: 0} 786 if peekValueType == UnsignedTypeV128 { 787 // InclusiveRange is the range in uint64 representation, so dropping a vector value on top 788 // should be translated as drop [0..1] inclusively. 789 r.End++ 790 } 791 c.emit(NewOperationDrop(r)) 792 case wasm.OpcodeSelect: 793 // If it is on the unreachable state, ignore the instruction. 794 if c.unreachableState.on { 795 break operatorSwitch 796 } 797 isTargetVector := c.stackPeek() == UnsignedTypeV128 798 c.emit( 799 NewOperationSelect(isTargetVector), 800 ) 801 case wasm.OpcodeTypedSelect: 802 // Skips two bytes: vector size fixed to 1, and the value type for select. 803 c.pc += 2 804 // If it is on the unreachable state, ignore the instruction. 805 if c.unreachableState.on { 806 break operatorSwitch 807 } 808 // Typed select is semantically equivalent to select at runtime. 809 isTargetVector := c.stackPeek() == UnsignedTypeV128 810 c.emit( 811 NewOperationSelect(isTargetVector), 812 ) 813 case wasm.OpcodeLocalGet: 814 depth := c.localDepth(index) 815 if isVector := c.localType(index) == wasm.ValueTypeV128; !isVector { 816 c.emit( 817 // -1 because we already manipulated the stack before 818 // called localDepth ^^. 819 NewOperationPick(depth-1, isVector), 820 ) 821 } else { 822 c.emit( 823 // -2 because we already manipulated the stack before 824 // called localDepth ^^. 825 NewOperationPick(depth-2, isVector), 826 ) 827 } 828 case wasm.OpcodeLocalSet: 829 depth := c.localDepth(index) 830 831 isVector := c.localType(index) == wasm.ValueTypeV128 832 if isVector { 833 c.emit( 834 // +2 because we already popped the operands for this operation from the c.stack before 835 // called localDepth ^^, 836 NewOperationSet(depth+2, isVector), 837 ) 838 } else { 839 c.emit( 840 // +1 because we already popped the operands for this operation from the c.stack before 841 // called localDepth ^^, 842 NewOperationSet(depth+1, isVector), 843 ) 844 } 845 case wasm.OpcodeLocalTee: 846 depth := c.localDepth(index) 847 isVector := c.localType(index) == wasm.ValueTypeV128 848 if isVector { 849 c.emit(NewOperationPick(1, isVector)) 850 c.emit(NewOperationSet(depth+2, isVector)) 851 } else { 852 c.emit( 853 NewOperationPick(0, isVector)) 854 c.emit(NewOperationSet(depth+1, isVector)) 855 } 856 case wasm.OpcodeGlobalGet: 857 c.emit( 858 NewOperationGlobalGet(index), 859 ) 860 case wasm.OpcodeGlobalSet: 861 c.emit( 862 NewOperationGlobalSet(index), 863 ) 864 case wasm.OpcodeI32Load: 865 imm, err := c.readMemoryArg(wasm.OpcodeI32LoadName) 866 if err != nil { 867 return err 868 } 869 c.emit(NewOperationLoad(UnsignedTypeI32, imm)) 870 case wasm.OpcodeI64Load: 871 imm, err := c.readMemoryArg(wasm.OpcodeI64LoadName) 872 if err != nil { 873 return err 874 } 875 c.emit(NewOperationLoad(UnsignedTypeI64, imm)) 876 case wasm.OpcodeF32Load: 877 imm, err := c.readMemoryArg(wasm.OpcodeF32LoadName) 878 if err != nil { 879 return err 880 } 881 c.emit(NewOperationLoad(UnsignedTypeF32, imm)) 882 case wasm.OpcodeF64Load: 883 imm, err := c.readMemoryArg(wasm.OpcodeF64LoadName) 884 if err != nil { 885 return err 886 } 887 c.emit(NewOperationLoad(UnsignedTypeF64, imm)) 888 case wasm.OpcodeI32Load8S: 889 imm, err := c.readMemoryArg(wasm.OpcodeI32Load8SName) 890 if err != nil { 891 return err 892 } 893 c.emit(NewOperationLoad8(SignedInt32, imm)) 894 case wasm.OpcodeI32Load8U: 895 imm, err := c.readMemoryArg(wasm.OpcodeI32Load8UName) 896 if err != nil { 897 return err 898 } 899 c.emit(NewOperationLoad8(SignedUint32, imm)) 900 case wasm.OpcodeI32Load16S: 901 imm, err := c.readMemoryArg(wasm.OpcodeI32Load16SName) 902 if err != nil { 903 return err 904 } 905 c.emit(NewOperationLoad16(SignedInt32, imm)) 906 case wasm.OpcodeI32Load16U: 907 imm, err := c.readMemoryArg(wasm.OpcodeI32Load16UName) 908 if err != nil { 909 return err 910 } 911 c.emit(NewOperationLoad16(SignedUint32, imm)) 912 case wasm.OpcodeI64Load8S: 913 imm, err := c.readMemoryArg(wasm.OpcodeI64Load8SName) 914 if err != nil { 915 return err 916 } 917 c.emit(NewOperationLoad8(SignedInt64, imm)) 918 case wasm.OpcodeI64Load8U: 919 imm, err := c.readMemoryArg(wasm.OpcodeI64Load8UName) 920 if err != nil { 921 return err 922 } 923 c.emit(NewOperationLoad8(SignedUint64, imm)) 924 case wasm.OpcodeI64Load16S: 925 imm, err := c.readMemoryArg(wasm.OpcodeI64Load16SName) 926 if err != nil { 927 return err 928 } 929 c.emit(NewOperationLoad16(SignedInt64, imm)) 930 case wasm.OpcodeI64Load16U: 931 imm, err := c.readMemoryArg(wasm.OpcodeI64Load16UName) 932 if err != nil { 933 return err 934 } 935 c.emit(NewOperationLoad16(SignedUint64, imm)) 936 case wasm.OpcodeI64Load32S: 937 imm, err := c.readMemoryArg(wasm.OpcodeI64Load32SName) 938 if err != nil { 939 return err 940 } 941 c.emit(NewOperationLoad32(true, imm)) 942 case wasm.OpcodeI64Load32U: 943 imm, err := c.readMemoryArg(wasm.OpcodeI64Load32UName) 944 if err != nil { 945 return err 946 } 947 c.emit(NewOperationLoad32(false, imm)) 948 case wasm.OpcodeI32Store: 949 imm, err := c.readMemoryArg(wasm.OpcodeI32StoreName) 950 if err != nil { 951 return err 952 } 953 c.emit( 954 NewOperationStore(UnsignedTypeI32, imm), 955 ) 956 case wasm.OpcodeI64Store: 957 imm, err := c.readMemoryArg(wasm.OpcodeI64StoreName) 958 if err != nil { 959 return err 960 } 961 c.emit( 962 NewOperationStore(UnsignedTypeI64, imm), 963 ) 964 case wasm.OpcodeF32Store: 965 imm, err := c.readMemoryArg(wasm.OpcodeF32StoreName) 966 if err != nil { 967 return err 968 } 969 c.emit( 970 NewOperationStore(UnsignedTypeF32, imm), 971 ) 972 case wasm.OpcodeF64Store: 973 imm, err := c.readMemoryArg(wasm.OpcodeF64StoreName) 974 if err != nil { 975 return err 976 } 977 c.emit( 978 NewOperationStore(UnsignedTypeF64, imm), 979 ) 980 case wasm.OpcodeI32Store8: 981 imm, err := c.readMemoryArg(wasm.OpcodeI32Store8Name) 982 if err != nil { 983 return err 984 } 985 c.emit( 986 NewOperationStore8(imm), 987 ) 988 case wasm.OpcodeI32Store16: 989 imm, err := c.readMemoryArg(wasm.OpcodeI32Store16Name) 990 if err != nil { 991 return err 992 } 993 c.emit( 994 NewOperationStore16(imm), 995 ) 996 case wasm.OpcodeI64Store8: 997 imm, err := c.readMemoryArg(wasm.OpcodeI64Store8Name) 998 if err != nil { 999 return err 1000 } 1001 c.emit( 1002 NewOperationStore8(imm), 1003 ) 1004 case wasm.OpcodeI64Store16: 1005 imm, err := c.readMemoryArg(wasm.OpcodeI64Store16Name) 1006 if err != nil { 1007 return err 1008 } 1009 c.emit( 1010 NewOperationStore16(imm), 1011 ) 1012 case wasm.OpcodeI64Store32: 1013 imm, err := c.readMemoryArg(wasm.OpcodeI64Store32Name) 1014 if err != nil { 1015 return err 1016 } 1017 c.emit( 1018 NewOperationStore32(imm), 1019 ) 1020 case wasm.OpcodeMemorySize: 1021 c.result.UsesMemory = true 1022 c.pc++ // Skip the reserved one byte. 1023 c.emit( 1024 NewOperationMemorySize(), 1025 ) 1026 case wasm.OpcodeMemoryGrow: 1027 c.result.UsesMemory = true 1028 c.pc++ // Skip the reserved one byte. 1029 c.emit( 1030 NewOperationMemoryGrow(), 1031 ) 1032 case wasm.OpcodeI32Const: 1033 val, num, err := leb128.LoadInt32(c.body[c.pc+1:]) 1034 if err != nil { 1035 return fmt.Errorf("reading i32.const value: %v", err) 1036 } 1037 c.pc += num 1038 c.emit( 1039 NewOperationConstI32(uint32(val)), 1040 ) 1041 case wasm.OpcodeI64Const: 1042 val, num, err := leb128.LoadInt64(c.body[c.pc+1:]) 1043 if err != nil { 1044 return fmt.Errorf("reading i64.const value: %v", err) 1045 } 1046 c.pc += num 1047 c.emit( 1048 NewOperationConstI64(uint64(val)), 1049 ) 1050 case wasm.OpcodeF32Const: 1051 v := math.Float32frombits(binary.LittleEndian.Uint32(c.body[c.pc+1:])) 1052 c.pc += 4 1053 c.emit( 1054 NewOperationConstF32(v), 1055 ) 1056 case wasm.OpcodeF64Const: 1057 v := math.Float64frombits(binary.LittleEndian.Uint64(c.body[c.pc+1:])) 1058 c.pc += 8 1059 c.emit( 1060 NewOperationConstF64(v), 1061 ) 1062 case wasm.OpcodeI32Eqz: 1063 c.emit( 1064 NewOperationEqz(UnsignedInt32), 1065 ) 1066 case wasm.OpcodeI32Eq: 1067 c.emit( 1068 NewOperationEq(UnsignedTypeI32), 1069 ) 1070 case wasm.OpcodeI32Ne: 1071 c.emit( 1072 NewOperationNe(UnsignedTypeI32), 1073 ) 1074 case wasm.OpcodeI32LtS: 1075 c.emit( 1076 NewOperationLt(SignedTypeInt32), 1077 ) 1078 case wasm.OpcodeI32LtU: 1079 c.emit( 1080 NewOperationLt(SignedTypeUint32), 1081 ) 1082 case wasm.OpcodeI32GtS: 1083 c.emit( 1084 NewOperationGt(SignedTypeInt32), 1085 ) 1086 case wasm.OpcodeI32GtU: 1087 c.emit( 1088 NewOperationGt(SignedTypeUint32), 1089 ) 1090 case wasm.OpcodeI32LeS: 1091 c.emit( 1092 NewOperationLe(SignedTypeInt32), 1093 ) 1094 case wasm.OpcodeI32LeU: 1095 c.emit( 1096 NewOperationLe(SignedTypeUint32), 1097 ) 1098 case wasm.OpcodeI32GeS: 1099 c.emit( 1100 NewOperationGe(SignedTypeInt32), 1101 ) 1102 case wasm.OpcodeI32GeU: 1103 c.emit( 1104 NewOperationGe(SignedTypeUint32), 1105 ) 1106 case wasm.OpcodeI64Eqz: 1107 c.emit( 1108 NewOperationEqz(UnsignedInt64), 1109 ) 1110 case wasm.OpcodeI64Eq: 1111 c.emit( 1112 NewOperationEq(UnsignedTypeI64), 1113 ) 1114 case wasm.OpcodeI64Ne: 1115 c.emit( 1116 NewOperationNe(UnsignedTypeI64), 1117 ) 1118 case wasm.OpcodeI64LtS: 1119 c.emit( 1120 NewOperationLt(SignedTypeInt64), 1121 ) 1122 case wasm.OpcodeI64LtU: 1123 c.emit( 1124 NewOperationLt(SignedTypeUint64), 1125 ) 1126 case wasm.OpcodeI64GtS: 1127 c.emit( 1128 NewOperationGt(SignedTypeInt64), 1129 ) 1130 case wasm.OpcodeI64GtU: 1131 c.emit( 1132 NewOperationGt(SignedTypeUint64), 1133 ) 1134 case wasm.OpcodeI64LeS: 1135 c.emit( 1136 NewOperationLe(SignedTypeInt64), 1137 ) 1138 case wasm.OpcodeI64LeU: 1139 c.emit( 1140 NewOperationLe(SignedTypeUint64), 1141 ) 1142 case wasm.OpcodeI64GeS: 1143 c.emit( 1144 NewOperationGe(SignedTypeInt64), 1145 ) 1146 case wasm.OpcodeI64GeU: 1147 c.emit( 1148 NewOperationGe(SignedTypeUint64), 1149 ) 1150 case wasm.OpcodeF32Eq: 1151 c.emit( 1152 NewOperationEq(UnsignedTypeF32), 1153 ) 1154 case wasm.OpcodeF32Ne: 1155 c.emit( 1156 NewOperationNe(UnsignedTypeF32), 1157 ) 1158 case wasm.OpcodeF32Lt: 1159 c.emit( 1160 NewOperationLt(SignedTypeFloat32), 1161 ) 1162 case wasm.OpcodeF32Gt: 1163 c.emit( 1164 NewOperationGt(SignedTypeFloat32), 1165 ) 1166 case wasm.OpcodeF32Le: 1167 c.emit( 1168 NewOperationLe(SignedTypeFloat32), 1169 ) 1170 case wasm.OpcodeF32Ge: 1171 c.emit( 1172 NewOperationGe(SignedTypeFloat32), 1173 ) 1174 case wasm.OpcodeF64Eq: 1175 c.emit( 1176 NewOperationEq(UnsignedTypeF64), 1177 ) 1178 case wasm.OpcodeF64Ne: 1179 c.emit( 1180 NewOperationNe(UnsignedTypeF64), 1181 ) 1182 case wasm.OpcodeF64Lt: 1183 c.emit( 1184 NewOperationLt(SignedTypeFloat64), 1185 ) 1186 case wasm.OpcodeF64Gt: 1187 c.emit( 1188 NewOperationGt(SignedTypeFloat64), 1189 ) 1190 case wasm.OpcodeF64Le: 1191 c.emit( 1192 NewOperationLe(SignedTypeFloat64), 1193 ) 1194 case wasm.OpcodeF64Ge: 1195 c.emit( 1196 NewOperationGe(SignedTypeFloat64), 1197 ) 1198 case wasm.OpcodeI32Clz: 1199 c.emit( 1200 NewOperationClz(UnsignedInt32), 1201 ) 1202 case wasm.OpcodeI32Ctz: 1203 c.emit( 1204 NewOperationCtz(UnsignedInt32), 1205 ) 1206 case wasm.OpcodeI32Popcnt: 1207 c.emit( 1208 NewOperationPopcnt(UnsignedInt32), 1209 ) 1210 case wasm.OpcodeI32Add: 1211 c.emit( 1212 NewOperationAdd(UnsignedTypeI32), 1213 ) 1214 case wasm.OpcodeI32Sub: 1215 c.emit( 1216 NewOperationSub(UnsignedTypeI32), 1217 ) 1218 case wasm.OpcodeI32Mul: 1219 c.emit( 1220 NewOperationMul(UnsignedTypeI32), 1221 ) 1222 case wasm.OpcodeI32DivS: 1223 c.emit( 1224 NewOperationDiv(SignedTypeInt32), 1225 ) 1226 case wasm.OpcodeI32DivU: 1227 c.emit( 1228 NewOperationDiv(SignedTypeUint32), 1229 ) 1230 case wasm.OpcodeI32RemS: 1231 c.emit( 1232 NewOperationRem(SignedInt32), 1233 ) 1234 case wasm.OpcodeI32RemU: 1235 c.emit( 1236 NewOperationRem(SignedUint32), 1237 ) 1238 case wasm.OpcodeI32And: 1239 c.emit( 1240 NewOperationAnd(UnsignedInt32), 1241 ) 1242 case wasm.OpcodeI32Or: 1243 c.emit( 1244 NewOperationOr(UnsignedInt32), 1245 ) 1246 case wasm.OpcodeI32Xor: 1247 c.emit( 1248 NewOperationXor(UnsignedInt64), 1249 ) 1250 case wasm.OpcodeI32Shl: 1251 c.emit( 1252 NewOperationShl(UnsignedInt32), 1253 ) 1254 case wasm.OpcodeI32ShrS: 1255 c.emit( 1256 NewOperationShr(SignedInt32), 1257 ) 1258 case wasm.OpcodeI32ShrU: 1259 c.emit( 1260 NewOperationShr(SignedUint32), 1261 ) 1262 case wasm.OpcodeI32Rotl: 1263 c.emit( 1264 NewOperationRotl(UnsignedInt32), 1265 ) 1266 case wasm.OpcodeI32Rotr: 1267 c.emit( 1268 NewOperationRotr(UnsignedInt32), 1269 ) 1270 case wasm.OpcodeI64Clz: 1271 c.emit( 1272 NewOperationClz(UnsignedInt64), 1273 ) 1274 case wasm.OpcodeI64Ctz: 1275 c.emit( 1276 NewOperationCtz(UnsignedInt64), 1277 ) 1278 case wasm.OpcodeI64Popcnt: 1279 c.emit( 1280 NewOperationPopcnt(UnsignedInt64), 1281 ) 1282 case wasm.OpcodeI64Add: 1283 c.emit( 1284 NewOperationAdd(UnsignedTypeI64), 1285 ) 1286 case wasm.OpcodeI64Sub: 1287 c.emit( 1288 NewOperationSub(UnsignedTypeI64), 1289 ) 1290 case wasm.OpcodeI64Mul: 1291 c.emit( 1292 NewOperationMul(UnsignedTypeI64), 1293 ) 1294 case wasm.OpcodeI64DivS: 1295 c.emit( 1296 NewOperationDiv(SignedTypeInt64), 1297 ) 1298 case wasm.OpcodeI64DivU: 1299 c.emit( 1300 NewOperationDiv(SignedTypeUint64), 1301 ) 1302 case wasm.OpcodeI64RemS: 1303 c.emit( 1304 NewOperationRem(SignedInt64), 1305 ) 1306 case wasm.OpcodeI64RemU: 1307 c.emit( 1308 NewOperationRem(SignedUint64), 1309 ) 1310 case wasm.OpcodeI64And: 1311 c.emit( 1312 NewOperationAnd(UnsignedInt64), 1313 ) 1314 case wasm.OpcodeI64Or: 1315 c.emit( 1316 NewOperationOr(UnsignedInt64), 1317 ) 1318 case wasm.OpcodeI64Xor: 1319 c.emit( 1320 NewOperationXor(UnsignedInt64), 1321 ) 1322 case wasm.OpcodeI64Shl: 1323 c.emit( 1324 NewOperationShl(UnsignedInt64), 1325 ) 1326 case wasm.OpcodeI64ShrS: 1327 c.emit( 1328 NewOperationShr(SignedInt64), 1329 ) 1330 case wasm.OpcodeI64ShrU: 1331 c.emit( 1332 NewOperationShr(SignedUint64), 1333 ) 1334 case wasm.OpcodeI64Rotl: 1335 c.emit( 1336 NewOperationRotl(UnsignedInt64), 1337 ) 1338 case wasm.OpcodeI64Rotr: 1339 c.emit( 1340 NewOperationRotr(UnsignedInt64), 1341 ) 1342 case wasm.OpcodeF32Abs: 1343 c.emit( 1344 NewOperationAbs(Float32), 1345 ) 1346 case wasm.OpcodeF32Neg: 1347 c.emit( 1348 NewOperationNeg(Float32), 1349 ) 1350 case wasm.OpcodeF32Ceil: 1351 c.emit( 1352 NewOperationCeil(Float32), 1353 ) 1354 case wasm.OpcodeF32Floor: 1355 c.emit( 1356 NewOperationFloor(Float32), 1357 ) 1358 case wasm.OpcodeF32Trunc: 1359 c.emit( 1360 NewOperationTrunc(Float32), 1361 ) 1362 case wasm.OpcodeF32Nearest: 1363 c.emit( 1364 NewOperationNearest(Float32), 1365 ) 1366 case wasm.OpcodeF32Sqrt: 1367 c.emit( 1368 NewOperationSqrt(Float32), 1369 ) 1370 case wasm.OpcodeF32Add: 1371 c.emit( 1372 NewOperationAdd(UnsignedTypeF32), 1373 ) 1374 case wasm.OpcodeF32Sub: 1375 c.emit( 1376 NewOperationSub(UnsignedTypeF32), 1377 ) 1378 case wasm.OpcodeF32Mul: 1379 c.emit( 1380 NewOperationMul(UnsignedTypeF32), 1381 ) 1382 case wasm.OpcodeF32Div: 1383 c.emit( 1384 NewOperationDiv(SignedTypeFloat32), 1385 ) 1386 case wasm.OpcodeF32Min: 1387 c.emit( 1388 NewOperationMin(Float32), 1389 ) 1390 case wasm.OpcodeF32Max: 1391 c.emit( 1392 NewOperationMax(Float32), 1393 ) 1394 case wasm.OpcodeF32Copysign: 1395 c.emit( 1396 NewOperationCopysign(Float32), 1397 ) 1398 case wasm.OpcodeF64Abs: 1399 c.emit( 1400 NewOperationAbs(Float64), 1401 ) 1402 case wasm.OpcodeF64Neg: 1403 c.emit( 1404 NewOperationNeg(Float64), 1405 ) 1406 case wasm.OpcodeF64Ceil: 1407 c.emit( 1408 NewOperationCeil(Float64), 1409 ) 1410 case wasm.OpcodeF64Floor: 1411 c.emit( 1412 NewOperationFloor(Float64), 1413 ) 1414 case wasm.OpcodeF64Trunc: 1415 c.emit( 1416 NewOperationTrunc(Float64), 1417 ) 1418 case wasm.OpcodeF64Nearest: 1419 c.emit( 1420 NewOperationNearest(Float64), 1421 ) 1422 case wasm.OpcodeF64Sqrt: 1423 c.emit( 1424 NewOperationSqrt(Float64), 1425 ) 1426 case wasm.OpcodeF64Add: 1427 c.emit( 1428 NewOperationAdd(UnsignedTypeF64), 1429 ) 1430 case wasm.OpcodeF64Sub: 1431 c.emit( 1432 NewOperationSub(UnsignedTypeF64), 1433 ) 1434 case wasm.OpcodeF64Mul: 1435 c.emit( 1436 NewOperationMul(UnsignedTypeF64), 1437 ) 1438 case wasm.OpcodeF64Div: 1439 c.emit( 1440 NewOperationDiv(SignedTypeFloat64), 1441 ) 1442 case wasm.OpcodeF64Min: 1443 c.emit( 1444 NewOperationMin(Float64), 1445 ) 1446 case wasm.OpcodeF64Max: 1447 c.emit( 1448 NewOperationMax(Float64), 1449 ) 1450 case wasm.OpcodeF64Copysign: 1451 c.emit( 1452 NewOperationCopysign(Float64), 1453 ) 1454 case wasm.OpcodeI32WrapI64: 1455 c.emit( 1456 NewOperationI32WrapFromI64(), 1457 ) 1458 case wasm.OpcodeI32TruncF32S: 1459 c.emit( 1460 NewOperationITruncFromF(Float32, SignedInt32, false), 1461 ) 1462 case wasm.OpcodeI32TruncF32U: 1463 c.emit( 1464 NewOperationITruncFromF(Float32, SignedUint32, false), 1465 ) 1466 case wasm.OpcodeI32TruncF64S: 1467 c.emit( 1468 NewOperationITruncFromF(Float64, SignedInt32, false), 1469 ) 1470 case wasm.OpcodeI32TruncF64U: 1471 c.emit( 1472 NewOperationITruncFromF(Float64, SignedUint32, false), 1473 ) 1474 case wasm.OpcodeI64ExtendI32S: 1475 c.emit( 1476 NewOperationExtend(true), 1477 ) 1478 case wasm.OpcodeI64ExtendI32U: 1479 c.emit( 1480 NewOperationExtend(false), 1481 ) 1482 case wasm.OpcodeI64TruncF32S: 1483 c.emit( 1484 NewOperationITruncFromF(Float32, SignedInt64, false), 1485 ) 1486 case wasm.OpcodeI64TruncF32U: 1487 c.emit( 1488 NewOperationITruncFromF(Float32, SignedUint64, false), 1489 ) 1490 case wasm.OpcodeI64TruncF64S: 1491 c.emit( 1492 NewOperationITruncFromF(Float64, SignedInt64, false), 1493 ) 1494 case wasm.OpcodeI64TruncF64U: 1495 c.emit( 1496 NewOperationITruncFromF(Float64, SignedUint64, false), 1497 ) 1498 case wasm.OpcodeF32ConvertI32S: 1499 c.emit( 1500 NewOperationFConvertFromI(SignedInt32, Float32), 1501 ) 1502 case wasm.OpcodeF32ConvertI32U: 1503 c.emit( 1504 NewOperationFConvertFromI(SignedUint32, Float32), 1505 ) 1506 case wasm.OpcodeF32ConvertI64S: 1507 c.emit( 1508 NewOperationFConvertFromI(SignedInt64, Float32), 1509 ) 1510 case wasm.OpcodeF32ConvertI64U: 1511 c.emit( 1512 NewOperationFConvertFromI(SignedUint64, Float32), 1513 ) 1514 case wasm.OpcodeF32DemoteF64: 1515 c.emit( 1516 NewOperationF32DemoteFromF64(), 1517 ) 1518 case wasm.OpcodeF64ConvertI32S: 1519 c.emit( 1520 NewOperationFConvertFromI(SignedInt32, Float64), 1521 ) 1522 case wasm.OpcodeF64ConvertI32U: 1523 c.emit( 1524 NewOperationFConvertFromI(SignedUint32, Float64), 1525 ) 1526 case wasm.OpcodeF64ConvertI64S: 1527 c.emit( 1528 NewOperationFConvertFromI(SignedInt64, Float64), 1529 ) 1530 case wasm.OpcodeF64ConvertI64U: 1531 c.emit( 1532 NewOperationFConvertFromI(SignedUint64, Float64), 1533 ) 1534 case wasm.OpcodeF64PromoteF32: 1535 c.emit( 1536 NewOperationF64PromoteFromF32(), 1537 ) 1538 case wasm.OpcodeI32ReinterpretF32: 1539 c.emit( 1540 NewOperationI32ReinterpretFromF32(), 1541 ) 1542 case wasm.OpcodeI64ReinterpretF64: 1543 c.emit( 1544 NewOperationI64ReinterpretFromF64(), 1545 ) 1546 case wasm.OpcodeF32ReinterpretI32: 1547 c.emit( 1548 NewOperationF32ReinterpretFromI32(), 1549 ) 1550 case wasm.OpcodeF64ReinterpretI64: 1551 c.emit( 1552 NewOperationF64ReinterpretFromI64(), 1553 ) 1554 case wasm.OpcodeI32Extend8S: 1555 c.emit( 1556 NewOperationSignExtend32From8(), 1557 ) 1558 case wasm.OpcodeI32Extend16S: 1559 c.emit( 1560 NewOperationSignExtend32From16(), 1561 ) 1562 case wasm.OpcodeI64Extend8S: 1563 c.emit( 1564 NewOperationSignExtend64From8(), 1565 ) 1566 case wasm.OpcodeI64Extend16S: 1567 c.emit( 1568 NewOperationSignExtend64From16(), 1569 ) 1570 case wasm.OpcodeI64Extend32S: 1571 c.emit( 1572 NewOperationSignExtend64From32(), 1573 ) 1574 case wasm.OpcodeRefFunc: 1575 c.pc++ 1576 index, num, err := leb128.LoadUint32(c.body[c.pc:]) 1577 if err != nil { 1578 return fmt.Errorf("failed to read function index for ref.func: %v", err) 1579 } 1580 c.pc += num - 1 1581 c.emit( 1582 NewOperationRefFunc(index), 1583 ) 1584 case wasm.OpcodeRefNull: 1585 c.pc++ // Skip the type of reftype as every ref value is opaque pointer. 1586 c.emit( 1587 NewOperationConstI64(0), 1588 ) 1589 case wasm.OpcodeRefIsNull: 1590 // Simply compare the opaque pointer (i64) with zero. 1591 c.emit( 1592 NewOperationEqz(UnsignedInt64), 1593 ) 1594 case wasm.OpcodeTableGet: 1595 c.pc++ 1596 tableIndex, num, err := leb128.LoadUint32(c.body[c.pc:]) 1597 if err != nil { 1598 return fmt.Errorf("failed to read function index for table.get: %v", err) 1599 } 1600 c.pc += num - 1 1601 c.emit( 1602 NewOperationTableGet(tableIndex), 1603 ) 1604 case wasm.OpcodeTableSet: 1605 c.pc++ 1606 tableIndex, num, err := leb128.LoadUint32(c.body[c.pc:]) 1607 if err != nil { 1608 return fmt.Errorf("failed to read function index for table.set: %v", err) 1609 } 1610 c.pc += num - 1 1611 c.emit( 1612 NewOperationTableSet(tableIndex), 1613 ) 1614 case wasm.OpcodeMiscPrefix: 1615 c.pc++ 1616 // A misc opcode is encoded as an unsigned variable 32-bit integer. 1617 miscOp, num, err := leb128.LoadUint32(c.body[c.pc:]) 1618 if err != nil { 1619 return fmt.Errorf("failed to read misc opcode: %v", err) 1620 } 1621 c.pc += num - 1 1622 switch byte(miscOp) { 1623 case wasm.OpcodeMiscI32TruncSatF32S: 1624 c.emit( 1625 NewOperationITruncFromF(Float32, SignedInt32, true), 1626 ) 1627 case wasm.OpcodeMiscI32TruncSatF32U: 1628 c.emit( 1629 NewOperationITruncFromF(Float32, SignedUint32, true), 1630 ) 1631 case wasm.OpcodeMiscI32TruncSatF64S: 1632 c.emit( 1633 NewOperationITruncFromF(Float64, SignedInt32, true), 1634 ) 1635 case wasm.OpcodeMiscI32TruncSatF64U: 1636 c.emit( 1637 NewOperationITruncFromF(Float64, SignedUint32, true), 1638 ) 1639 case wasm.OpcodeMiscI64TruncSatF32S: 1640 c.emit( 1641 NewOperationITruncFromF(Float32, SignedInt64, true), 1642 ) 1643 case wasm.OpcodeMiscI64TruncSatF32U: 1644 c.emit( 1645 NewOperationITruncFromF(Float32, SignedUint64, true), 1646 ) 1647 case wasm.OpcodeMiscI64TruncSatF64S: 1648 c.emit( 1649 NewOperationITruncFromF(Float64, SignedInt64, true), 1650 ) 1651 case wasm.OpcodeMiscI64TruncSatF64U: 1652 c.emit( 1653 NewOperationITruncFromF(Float64, SignedUint64, true), 1654 ) 1655 case wasm.OpcodeMiscMemoryInit: 1656 c.result.UsesMemory = true 1657 dataIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) 1658 if err != nil { 1659 return fmt.Errorf("reading i32.const value: %v", err) 1660 } 1661 c.pc += num + 1 // +1 to skip the memory index which is fixed to zero. 1662 c.emit( 1663 NewOperationMemoryInit(dataIndex), 1664 ) 1665 case wasm.OpcodeMiscDataDrop: 1666 dataIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) 1667 if err != nil { 1668 return fmt.Errorf("reading i32.const value: %v", err) 1669 } 1670 c.pc += num 1671 c.emit( 1672 NewOperationDataDrop(dataIndex), 1673 ) 1674 case wasm.OpcodeMiscMemoryCopy: 1675 c.result.UsesMemory = true 1676 c.pc += 2 // +2 to skip two memory indexes which are fixed to zero. 1677 c.emit( 1678 NewOperationMemoryCopy(), 1679 ) 1680 case wasm.OpcodeMiscMemoryFill: 1681 c.result.UsesMemory = true 1682 c.pc += 1 // +1 to skip the memory index which is fixed to zero. 1683 c.emit( 1684 NewOperationMemoryFill(), 1685 ) 1686 case wasm.OpcodeMiscTableInit: 1687 elemIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) 1688 if err != nil { 1689 return fmt.Errorf("reading i32.const value: %v", err) 1690 } 1691 c.pc += num 1692 // Read table index which is fixed to zero currently. 1693 tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) 1694 if err != nil { 1695 return fmt.Errorf("reading i32.const value: %v", err) 1696 } 1697 c.pc += num 1698 c.emit( 1699 NewOperationTableInit(elemIndex, tableIndex), 1700 ) 1701 case wasm.OpcodeMiscElemDrop: 1702 elemIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) 1703 if err != nil { 1704 return fmt.Errorf("reading i32.const value: %v", err) 1705 } 1706 c.pc += num 1707 c.emit( 1708 NewOperationElemDrop(elemIndex), 1709 ) 1710 case wasm.OpcodeMiscTableCopy: 1711 // Read the source table inde.g. 1712 dst, num, err := leb128.LoadUint32(c.body[c.pc+1:]) 1713 if err != nil { 1714 return fmt.Errorf("reading i32.const value: %v", err) 1715 } 1716 c.pc += num 1717 // Read the destination table inde.g. 1718 src, num, err := leb128.LoadUint32(c.body[c.pc+1:]) 1719 if err != nil { 1720 return fmt.Errorf("reading i32.const value: %v", err) 1721 } 1722 c.pc += num 1723 c.emit( 1724 NewOperationTableCopy(src, dst), 1725 ) 1726 case wasm.OpcodeMiscTableGrow: 1727 // Read the source table inde.g. 1728 tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) 1729 if err != nil { 1730 return fmt.Errorf("reading i32.const value: %v", err) 1731 } 1732 c.pc += num 1733 c.emit( 1734 NewOperationTableGrow(tableIndex), 1735 ) 1736 case wasm.OpcodeMiscTableSize: 1737 // Read the source table inde.g. 1738 tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) 1739 if err != nil { 1740 return fmt.Errorf("reading i32.const value: %v", err) 1741 } 1742 c.pc += num 1743 c.emit( 1744 NewOperationTableSize(tableIndex), 1745 ) 1746 case wasm.OpcodeMiscTableFill: 1747 // Read the source table index. 1748 tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) 1749 if err != nil { 1750 return fmt.Errorf("reading i32.const value: %v", err) 1751 } 1752 c.pc += num 1753 c.emit( 1754 NewOperationTableFill(tableIndex), 1755 ) 1756 default: 1757 return fmt.Errorf("unsupported misc instruction in wazeroir: 0x%x", op) 1758 } 1759 case wasm.OpcodeVecPrefix: 1760 c.pc++ 1761 switch vecOp := c.body[c.pc]; vecOp { 1762 case wasm.OpcodeVecV128Const: 1763 c.pc++ 1764 lo := binary.LittleEndian.Uint64(c.body[c.pc : c.pc+8]) 1765 c.pc += 8 1766 hi := binary.LittleEndian.Uint64(c.body[c.pc : c.pc+8]) 1767 c.emit( 1768 NewOperationV128Const(lo, hi), 1769 ) 1770 c.pc += 7 1771 case wasm.OpcodeVecV128Load: 1772 arg, err := c.readMemoryArg(wasm.OpcodeI32LoadName) 1773 if err != nil { 1774 return err 1775 } 1776 c.emit( 1777 NewOperationV128Load(V128LoadType128, arg), 1778 ) 1779 case wasm.OpcodeVecV128Load8x8s: 1780 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8x8SName) 1781 if err != nil { 1782 return err 1783 } 1784 c.emit( 1785 NewOperationV128Load(V128LoadType8x8s, arg), 1786 ) 1787 case wasm.OpcodeVecV128Load8x8u: 1788 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8x8UName) 1789 if err != nil { 1790 return err 1791 } 1792 c.emit( 1793 NewOperationV128Load(V128LoadType8x8u, arg), 1794 ) 1795 case wasm.OpcodeVecV128Load16x4s: 1796 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16x4SName) 1797 if err != nil { 1798 return err 1799 } 1800 c.emit( 1801 NewOperationV128Load(V128LoadType16x4s, arg), 1802 ) 1803 case wasm.OpcodeVecV128Load16x4u: 1804 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16x4UName) 1805 if err != nil { 1806 return err 1807 } 1808 c.emit( 1809 NewOperationV128Load(V128LoadType16x4u, arg), 1810 ) 1811 case wasm.OpcodeVecV128Load32x2s: 1812 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32x2SName) 1813 if err != nil { 1814 return err 1815 } 1816 c.emit( 1817 NewOperationV128Load(V128LoadType32x2s, arg), 1818 ) 1819 case wasm.OpcodeVecV128Load32x2u: 1820 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32x2UName) 1821 if err != nil { 1822 return err 1823 } 1824 c.emit( 1825 NewOperationV128Load(V128LoadType32x2u, arg), 1826 ) 1827 case wasm.OpcodeVecV128Load8Splat: 1828 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8SplatName) 1829 if err != nil { 1830 return err 1831 } 1832 c.emit( 1833 NewOperationV128Load(V128LoadType8Splat, arg), 1834 ) 1835 case wasm.OpcodeVecV128Load16Splat: 1836 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16SplatName) 1837 if err != nil { 1838 return err 1839 } 1840 c.emit( 1841 NewOperationV128Load(V128LoadType16Splat, arg), 1842 ) 1843 case wasm.OpcodeVecV128Load32Splat: 1844 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32SplatName) 1845 if err != nil { 1846 return err 1847 } 1848 c.emit( 1849 NewOperationV128Load(V128LoadType32Splat, arg), 1850 ) 1851 case wasm.OpcodeVecV128Load64Splat: 1852 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64SplatName) 1853 if err != nil { 1854 return err 1855 } 1856 c.emit( 1857 NewOperationV128Load(V128LoadType64Splat, arg), 1858 ) 1859 case wasm.OpcodeVecV128Load32zero: 1860 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32zeroName) 1861 if err != nil { 1862 return err 1863 } 1864 c.emit( 1865 NewOperationV128Load(V128LoadType32zero, arg), 1866 ) 1867 case wasm.OpcodeVecV128Load64zero: 1868 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64zeroName) 1869 if err != nil { 1870 return err 1871 } 1872 c.emit( 1873 NewOperationV128Load(V128LoadType64zero, arg), 1874 ) 1875 case wasm.OpcodeVecV128Load8Lane: 1876 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8LaneName) 1877 if err != nil { 1878 return err 1879 } 1880 c.pc++ 1881 laneIndex := c.body[c.pc] 1882 c.emit( 1883 NewOperationV128LoadLane(laneIndex, 8, arg), 1884 ) 1885 case wasm.OpcodeVecV128Load16Lane: 1886 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16LaneName) 1887 if err != nil { 1888 return err 1889 } 1890 c.pc++ 1891 laneIndex := c.body[c.pc] 1892 c.emit( 1893 NewOperationV128LoadLane(laneIndex, 16, arg), 1894 ) 1895 case wasm.OpcodeVecV128Load32Lane: 1896 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32LaneName) 1897 if err != nil { 1898 return err 1899 } 1900 c.pc++ 1901 laneIndex := c.body[c.pc] 1902 c.emit( 1903 NewOperationV128LoadLane(laneIndex, 32, arg), 1904 ) 1905 case wasm.OpcodeVecV128Load64Lane: 1906 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64LaneName) 1907 if err != nil { 1908 return err 1909 } 1910 c.pc++ 1911 laneIndex := c.body[c.pc] 1912 c.emit( 1913 NewOperationV128LoadLane(laneIndex, 64, arg), 1914 ) 1915 case wasm.OpcodeVecV128Store: 1916 arg, err := c.readMemoryArg(wasm.OpcodeVecV128StoreName) 1917 if err != nil { 1918 return err 1919 } 1920 c.emit( 1921 NewOperationV128Store(arg), 1922 ) 1923 case wasm.OpcodeVecV128Store8Lane: 1924 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store8LaneName) 1925 if err != nil { 1926 return err 1927 } 1928 c.pc++ 1929 laneIndex := c.body[c.pc] 1930 c.emit( 1931 NewOperationV128StoreLane(laneIndex, 8, arg), 1932 ) 1933 case wasm.OpcodeVecV128Store16Lane: 1934 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store16LaneName) 1935 if err != nil { 1936 return err 1937 } 1938 c.pc++ 1939 laneIndex := c.body[c.pc] 1940 c.emit( 1941 NewOperationV128StoreLane(laneIndex, 16, arg), 1942 ) 1943 case wasm.OpcodeVecV128Store32Lane: 1944 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store32LaneName) 1945 if err != nil { 1946 return err 1947 } 1948 c.pc++ 1949 laneIndex := c.body[c.pc] 1950 c.emit( 1951 NewOperationV128StoreLane(laneIndex, 32, arg), 1952 ) 1953 case wasm.OpcodeVecV128Store64Lane: 1954 arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store64LaneName) 1955 if err != nil { 1956 return err 1957 } 1958 c.pc++ 1959 laneIndex := c.body[c.pc] 1960 c.emit( 1961 NewOperationV128StoreLane(laneIndex, 64, arg), 1962 ) 1963 case wasm.OpcodeVecI8x16ExtractLaneS: 1964 c.pc++ 1965 laneIndex := c.body[c.pc] 1966 c.emit( 1967 NewOperationV128ExtractLane(laneIndex, true, ShapeI8x16), 1968 ) 1969 case wasm.OpcodeVecI8x16ExtractLaneU: 1970 c.pc++ 1971 laneIndex := c.body[c.pc] 1972 c.emit( 1973 NewOperationV128ExtractLane(laneIndex, false, ShapeI8x16), 1974 ) 1975 case wasm.OpcodeVecI16x8ExtractLaneS: 1976 c.pc++ 1977 laneIndex := c.body[c.pc] 1978 c.emit( 1979 NewOperationV128ExtractLane(laneIndex, true, ShapeI16x8), 1980 ) 1981 case wasm.OpcodeVecI16x8ExtractLaneU: 1982 c.pc++ 1983 laneIndex := c.body[c.pc] 1984 c.emit( 1985 NewOperationV128ExtractLane(laneIndex, false, ShapeI16x8), 1986 ) 1987 case wasm.OpcodeVecI32x4ExtractLane: 1988 c.pc++ 1989 laneIndex := c.body[c.pc] 1990 c.emit( 1991 NewOperationV128ExtractLane(laneIndex, false, ShapeI32x4), 1992 ) 1993 case wasm.OpcodeVecI64x2ExtractLane: 1994 c.pc++ 1995 laneIndex := c.body[c.pc] 1996 c.emit( 1997 NewOperationV128ExtractLane(laneIndex, false, ShapeI64x2), 1998 ) 1999 case wasm.OpcodeVecF32x4ExtractLane: 2000 c.pc++ 2001 laneIndex := c.body[c.pc] 2002 c.emit( 2003 NewOperationV128ExtractLane(laneIndex, false, ShapeF32x4), 2004 ) 2005 case wasm.OpcodeVecF64x2ExtractLane: 2006 c.pc++ 2007 laneIndex := c.body[c.pc] 2008 c.emit( 2009 NewOperationV128ExtractLane(laneIndex, false, ShapeF64x2), 2010 ) 2011 case wasm.OpcodeVecI8x16ReplaceLane: 2012 c.pc++ 2013 laneIndex := c.body[c.pc] 2014 c.emit( 2015 NewOperationV128ReplaceLane(laneIndex, ShapeI8x16), 2016 ) 2017 case wasm.OpcodeVecI16x8ReplaceLane: 2018 c.pc++ 2019 laneIndex := c.body[c.pc] 2020 c.emit( 2021 NewOperationV128ReplaceLane(laneIndex, ShapeI16x8), 2022 ) 2023 case wasm.OpcodeVecI32x4ReplaceLane: 2024 c.pc++ 2025 laneIndex := c.body[c.pc] 2026 c.emit( 2027 NewOperationV128ReplaceLane(laneIndex, ShapeI32x4), 2028 ) 2029 case wasm.OpcodeVecI64x2ReplaceLane: 2030 c.pc++ 2031 laneIndex := c.body[c.pc] 2032 c.emit( 2033 NewOperationV128ReplaceLane(laneIndex, ShapeI64x2), 2034 ) 2035 case wasm.OpcodeVecF32x4ReplaceLane: 2036 c.pc++ 2037 laneIndex := c.body[c.pc] 2038 c.emit( 2039 NewOperationV128ReplaceLane(laneIndex, ShapeF32x4), 2040 ) 2041 case wasm.OpcodeVecF64x2ReplaceLane: 2042 c.pc++ 2043 laneIndex := c.body[c.pc] 2044 c.emit( 2045 NewOperationV128ReplaceLane(laneIndex, ShapeF64x2), 2046 ) 2047 case wasm.OpcodeVecI8x16Splat: 2048 c.emit( 2049 NewOperationV128Splat(ShapeI8x16), 2050 ) 2051 case wasm.OpcodeVecI16x8Splat: 2052 c.emit( 2053 NewOperationV128Splat(ShapeI16x8), 2054 ) 2055 case wasm.OpcodeVecI32x4Splat: 2056 c.emit( 2057 NewOperationV128Splat(ShapeI32x4), 2058 ) 2059 case wasm.OpcodeVecI64x2Splat: 2060 c.emit( 2061 NewOperationV128Splat(ShapeI64x2), 2062 ) 2063 case wasm.OpcodeVecF32x4Splat: 2064 c.emit( 2065 NewOperationV128Splat(ShapeF32x4), 2066 ) 2067 case wasm.OpcodeVecF64x2Splat: 2068 c.emit( 2069 NewOperationV128Splat(ShapeF64x2), 2070 ) 2071 case wasm.OpcodeVecI8x16Swizzle: 2072 c.emit( 2073 NewOperationV128Swizzle(), 2074 ) 2075 case wasm.OpcodeVecV128i8x16Shuffle: 2076 c.pc++ 2077 lanes := make([]uint64, 16) 2078 for i := uint64(0); i < 16; i++ { 2079 lanes[i] = uint64(c.body[c.pc+i]) 2080 } 2081 op := NewOperationV128Shuffle(lanes) 2082 c.emit(op) 2083 c.pc += 15 2084 case wasm.OpcodeVecV128AnyTrue: 2085 c.emit( 2086 NewOperationV128AnyTrue(), 2087 ) 2088 case wasm.OpcodeVecI8x16AllTrue: 2089 c.emit( 2090 NewOperationV128AllTrue(ShapeI8x16), 2091 ) 2092 case wasm.OpcodeVecI16x8AllTrue: 2093 c.emit( 2094 NewOperationV128AllTrue(ShapeI16x8), 2095 ) 2096 case wasm.OpcodeVecI32x4AllTrue: 2097 c.emit( 2098 NewOperationV128AllTrue(ShapeI32x4), 2099 ) 2100 case wasm.OpcodeVecI64x2AllTrue: 2101 c.emit( 2102 NewOperationV128AllTrue(ShapeI64x2), 2103 ) 2104 case wasm.OpcodeVecI8x16BitMask: 2105 c.emit( 2106 NewOperationV128BitMask(ShapeI8x16), 2107 ) 2108 case wasm.OpcodeVecI16x8BitMask: 2109 c.emit( 2110 NewOperationV128BitMask(ShapeI16x8), 2111 ) 2112 case wasm.OpcodeVecI32x4BitMask: 2113 c.emit( 2114 NewOperationV128BitMask(ShapeI32x4), 2115 ) 2116 case wasm.OpcodeVecI64x2BitMask: 2117 c.emit( 2118 NewOperationV128BitMask(ShapeI64x2), 2119 ) 2120 case wasm.OpcodeVecV128And: 2121 c.emit( 2122 NewOperationV128And(), 2123 ) 2124 case wasm.OpcodeVecV128Not: 2125 c.emit( 2126 NewOperationV128Not(), 2127 ) 2128 case wasm.OpcodeVecV128Or: 2129 c.emit( 2130 NewOperationV128Or(), 2131 ) 2132 case wasm.OpcodeVecV128Xor: 2133 c.emit( 2134 NewOperationV128Xor(), 2135 ) 2136 case wasm.OpcodeVecV128Bitselect: 2137 c.emit( 2138 NewOperationV128Bitselect(), 2139 ) 2140 case wasm.OpcodeVecV128AndNot: 2141 c.emit( 2142 NewOperationV128AndNot(), 2143 ) 2144 case wasm.OpcodeVecI8x16Shl: 2145 c.emit( 2146 NewOperationV128Shl(ShapeI8x16), 2147 ) 2148 case wasm.OpcodeVecI8x16ShrS: 2149 c.emit( 2150 NewOperationV128Shr(ShapeI8x16, true), 2151 ) 2152 case wasm.OpcodeVecI8x16ShrU: 2153 c.emit( 2154 NewOperationV128Shr(ShapeI8x16, false), 2155 ) 2156 case wasm.OpcodeVecI16x8Shl: 2157 c.emit( 2158 NewOperationV128Shl(ShapeI16x8), 2159 ) 2160 case wasm.OpcodeVecI16x8ShrS: 2161 c.emit( 2162 NewOperationV128Shr(ShapeI16x8, true), 2163 ) 2164 case wasm.OpcodeVecI16x8ShrU: 2165 c.emit( 2166 NewOperationV128Shr(ShapeI16x8, false), 2167 ) 2168 case wasm.OpcodeVecI32x4Shl: 2169 c.emit( 2170 NewOperationV128Shl(ShapeI32x4), 2171 ) 2172 case wasm.OpcodeVecI32x4ShrS: 2173 c.emit( 2174 NewOperationV128Shr(ShapeI32x4, true), 2175 ) 2176 case wasm.OpcodeVecI32x4ShrU: 2177 c.emit( 2178 NewOperationV128Shr(ShapeI32x4, false), 2179 ) 2180 case wasm.OpcodeVecI64x2Shl: 2181 c.emit( 2182 NewOperationV128Shl(ShapeI64x2), 2183 ) 2184 case wasm.OpcodeVecI64x2ShrS: 2185 c.emit( 2186 NewOperationV128Shr(ShapeI64x2, true), 2187 ) 2188 case wasm.OpcodeVecI64x2ShrU: 2189 c.emit( 2190 NewOperationV128Shr(ShapeI64x2, false), 2191 ) 2192 case wasm.OpcodeVecI8x16Eq: 2193 c.emit( 2194 NewOperationV128Cmp(V128CmpTypeI8x16Eq), 2195 ) 2196 case wasm.OpcodeVecI8x16Ne: 2197 c.emit( 2198 NewOperationV128Cmp(V128CmpTypeI8x16Ne), 2199 ) 2200 case wasm.OpcodeVecI8x16LtS: 2201 c.emit( 2202 NewOperationV128Cmp(V128CmpTypeI8x16LtS), 2203 ) 2204 case wasm.OpcodeVecI8x16LtU: 2205 c.emit( 2206 NewOperationV128Cmp(V128CmpTypeI8x16LtU), 2207 ) 2208 case wasm.OpcodeVecI8x16GtS: 2209 c.emit( 2210 NewOperationV128Cmp(V128CmpTypeI8x16GtS), 2211 ) 2212 case wasm.OpcodeVecI8x16GtU: 2213 c.emit( 2214 NewOperationV128Cmp(V128CmpTypeI8x16GtU), 2215 ) 2216 case wasm.OpcodeVecI8x16LeS: 2217 c.emit( 2218 NewOperationV128Cmp(V128CmpTypeI8x16LeS), 2219 ) 2220 case wasm.OpcodeVecI8x16LeU: 2221 c.emit( 2222 NewOperationV128Cmp(V128CmpTypeI8x16LeU), 2223 ) 2224 case wasm.OpcodeVecI8x16GeS: 2225 c.emit( 2226 NewOperationV128Cmp(V128CmpTypeI8x16GeS), 2227 ) 2228 case wasm.OpcodeVecI8x16GeU: 2229 c.emit( 2230 NewOperationV128Cmp(V128CmpTypeI8x16GeU), 2231 ) 2232 case wasm.OpcodeVecI16x8Eq: 2233 c.emit( 2234 NewOperationV128Cmp(V128CmpTypeI16x8Eq), 2235 ) 2236 case wasm.OpcodeVecI16x8Ne: 2237 c.emit( 2238 NewOperationV128Cmp(V128CmpTypeI16x8Ne), 2239 ) 2240 case wasm.OpcodeVecI16x8LtS: 2241 c.emit( 2242 NewOperationV128Cmp(V128CmpTypeI16x8LtS), 2243 ) 2244 case wasm.OpcodeVecI16x8LtU: 2245 c.emit( 2246 NewOperationV128Cmp(V128CmpTypeI16x8LtU), 2247 ) 2248 case wasm.OpcodeVecI16x8GtS: 2249 c.emit( 2250 NewOperationV128Cmp(V128CmpTypeI16x8GtS), 2251 ) 2252 case wasm.OpcodeVecI16x8GtU: 2253 c.emit( 2254 NewOperationV128Cmp(V128CmpTypeI16x8GtU), 2255 ) 2256 case wasm.OpcodeVecI16x8LeS: 2257 c.emit( 2258 NewOperationV128Cmp(V128CmpTypeI16x8LeS), 2259 ) 2260 case wasm.OpcodeVecI16x8LeU: 2261 c.emit( 2262 NewOperationV128Cmp(V128CmpTypeI16x8LeU), 2263 ) 2264 case wasm.OpcodeVecI16x8GeS: 2265 c.emit( 2266 NewOperationV128Cmp(V128CmpTypeI16x8GeS), 2267 ) 2268 case wasm.OpcodeVecI16x8GeU: 2269 c.emit( 2270 NewOperationV128Cmp(V128CmpTypeI16x8GeU), 2271 ) 2272 case wasm.OpcodeVecI32x4Eq: 2273 c.emit( 2274 NewOperationV128Cmp(V128CmpTypeI32x4Eq), 2275 ) 2276 case wasm.OpcodeVecI32x4Ne: 2277 c.emit( 2278 NewOperationV128Cmp(V128CmpTypeI32x4Ne), 2279 ) 2280 case wasm.OpcodeVecI32x4LtS: 2281 c.emit( 2282 NewOperationV128Cmp(V128CmpTypeI32x4LtS), 2283 ) 2284 case wasm.OpcodeVecI32x4LtU: 2285 c.emit( 2286 NewOperationV128Cmp(V128CmpTypeI32x4LtU), 2287 ) 2288 case wasm.OpcodeVecI32x4GtS: 2289 c.emit( 2290 NewOperationV128Cmp(V128CmpTypeI32x4GtS), 2291 ) 2292 case wasm.OpcodeVecI32x4GtU: 2293 c.emit( 2294 NewOperationV128Cmp(V128CmpTypeI32x4GtU), 2295 ) 2296 case wasm.OpcodeVecI32x4LeS: 2297 c.emit( 2298 NewOperationV128Cmp(V128CmpTypeI32x4LeS), 2299 ) 2300 case wasm.OpcodeVecI32x4LeU: 2301 c.emit( 2302 NewOperationV128Cmp(V128CmpTypeI32x4LeU), 2303 ) 2304 case wasm.OpcodeVecI32x4GeS: 2305 c.emit( 2306 NewOperationV128Cmp(V128CmpTypeI32x4GeS), 2307 ) 2308 case wasm.OpcodeVecI32x4GeU: 2309 c.emit( 2310 NewOperationV128Cmp(V128CmpTypeI32x4GeU), 2311 ) 2312 case wasm.OpcodeVecI64x2Eq: 2313 c.emit( 2314 NewOperationV128Cmp(V128CmpTypeI64x2Eq), 2315 ) 2316 case wasm.OpcodeVecI64x2Ne: 2317 c.emit( 2318 NewOperationV128Cmp(V128CmpTypeI64x2Ne), 2319 ) 2320 case wasm.OpcodeVecI64x2LtS: 2321 c.emit( 2322 NewOperationV128Cmp(V128CmpTypeI64x2LtS), 2323 ) 2324 case wasm.OpcodeVecI64x2GtS: 2325 c.emit( 2326 NewOperationV128Cmp(V128CmpTypeI64x2GtS), 2327 ) 2328 case wasm.OpcodeVecI64x2LeS: 2329 c.emit( 2330 NewOperationV128Cmp(V128CmpTypeI64x2LeS), 2331 ) 2332 case wasm.OpcodeVecI64x2GeS: 2333 c.emit( 2334 NewOperationV128Cmp(V128CmpTypeI64x2GeS), 2335 ) 2336 case wasm.OpcodeVecF32x4Eq: 2337 c.emit( 2338 NewOperationV128Cmp(V128CmpTypeF32x4Eq), 2339 ) 2340 case wasm.OpcodeVecF32x4Ne: 2341 c.emit( 2342 NewOperationV128Cmp(V128CmpTypeF32x4Ne), 2343 ) 2344 case wasm.OpcodeVecF32x4Lt: 2345 c.emit( 2346 NewOperationV128Cmp(V128CmpTypeF32x4Lt), 2347 ) 2348 case wasm.OpcodeVecF32x4Gt: 2349 c.emit( 2350 NewOperationV128Cmp(V128CmpTypeF32x4Gt), 2351 ) 2352 case wasm.OpcodeVecF32x4Le: 2353 c.emit( 2354 NewOperationV128Cmp(V128CmpTypeF32x4Le), 2355 ) 2356 case wasm.OpcodeVecF32x4Ge: 2357 c.emit( 2358 NewOperationV128Cmp(V128CmpTypeF32x4Ge), 2359 ) 2360 case wasm.OpcodeVecF64x2Eq: 2361 c.emit( 2362 NewOperationV128Cmp(V128CmpTypeF64x2Eq), 2363 ) 2364 case wasm.OpcodeVecF64x2Ne: 2365 c.emit( 2366 NewOperationV128Cmp(V128CmpTypeF64x2Ne), 2367 ) 2368 case wasm.OpcodeVecF64x2Lt: 2369 c.emit( 2370 NewOperationV128Cmp(V128CmpTypeF64x2Lt), 2371 ) 2372 case wasm.OpcodeVecF64x2Gt: 2373 c.emit( 2374 NewOperationV128Cmp(V128CmpTypeF64x2Gt), 2375 ) 2376 case wasm.OpcodeVecF64x2Le: 2377 c.emit( 2378 NewOperationV128Cmp(V128CmpTypeF64x2Le), 2379 ) 2380 case wasm.OpcodeVecF64x2Ge: 2381 c.emit( 2382 NewOperationV128Cmp(V128CmpTypeF64x2Ge), 2383 ) 2384 case wasm.OpcodeVecI8x16Neg: 2385 c.emit( 2386 NewOperationV128Neg(ShapeI8x16), 2387 ) 2388 case wasm.OpcodeVecI16x8Neg: 2389 c.emit( 2390 NewOperationV128Neg(ShapeI16x8), 2391 ) 2392 case wasm.OpcodeVecI32x4Neg: 2393 c.emit( 2394 NewOperationV128Neg(ShapeI32x4), 2395 ) 2396 case wasm.OpcodeVecI64x2Neg: 2397 c.emit( 2398 NewOperationV128Neg(ShapeI64x2), 2399 ) 2400 case wasm.OpcodeVecF32x4Neg: 2401 c.emit( 2402 NewOperationV128Neg(ShapeF32x4), 2403 ) 2404 case wasm.OpcodeVecF64x2Neg: 2405 c.emit( 2406 NewOperationV128Neg(ShapeF64x2), 2407 ) 2408 case wasm.OpcodeVecI8x16Add: 2409 c.emit( 2410 NewOperationV128Add(ShapeI8x16), 2411 ) 2412 case wasm.OpcodeVecI16x8Add: 2413 c.emit( 2414 NewOperationV128Add(ShapeI16x8), 2415 ) 2416 case wasm.OpcodeVecI32x4Add: 2417 c.emit( 2418 NewOperationV128Add(ShapeI32x4), 2419 ) 2420 case wasm.OpcodeVecI64x2Add: 2421 c.emit( 2422 NewOperationV128Add(ShapeI64x2), 2423 ) 2424 case wasm.OpcodeVecF32x4Add: 2425 c.emit( 2426 NewOperationV128Add(ShapeF32x4), 2427 ) 2428 case wasm.OpcodeVecF64x2Add: 2429 c.emit( 2430 NewOperationV128Add(ShapeF64x2), 2431 ) 2432 case wasm.OpcodeVecI8x16Sub: 2433 c.emit( 2434 NewOperationV128Sub(ShapeI8x16), 2435 ) 2436 case wasm.OpcodeVecI16x8Sub: 2437 c.emit( 2438 NewOperationV128Sub(ShapeI16x8), 2439 ) 2440 case wasm.OpcodeVecI32x4Sub: 2441 c.emit( 2442 NewOperationV128Sub(ShapeI32x4), 2443 ) 2444 case wasm.OpcodeVecI64x2Sub: 2445 c.emit( 2446 NewOperationV128Sub(ShapeI64x2), 2447 ) 2448 case wasm.OpcodeVecF32x4Sub: 2449 c.emit( 2450 NewOperationV128Sub(ShapeF32x4), 2451 ) 2452 case wasm.OpcodeVecF64x2Sub: 2453 c.emit( 2454 NewOperationV128Sub(ShapeF64x2), 2455 ) 2456 case wasm.OpcodeVecI8x16AddSatS: 2457 c.emit( 2458 NewOperationV128AddSat(ShapeI8x16, true), 2459 ) 2460 case wasm.OpcodeVecI8x16AddSatU: 2461 c.emit( 2462 NewOperationV128AddSat(ShapeI8x16, false), 2463 ) 2464 case wasm.OpcodeVecI16x8AddSatS: 2465 c.emit( 2466 NewOperationV128AddSat(ShapeI16x8, true), 2467 ) 2468 case wasm.OpcodeVecI16x8AddSatU: 2469 c.emit( 2470 NewOperationV128AddSat(ShapeI16x8, false), 2471 ) 2472 case wasm.OpcodeVecI8x16SubSatS: 2473 c.emit( 2474 NewOperationV128SubSat(ShapeI8x16, true), 2475 ) 2476 case wasm.OpcodeVecI8x16SubSatU: 2477 c.emit( 2478 NewOperationV128SubSat(ShapeI8x16, false), 2479 ) 2480 case wasm.OpcodeVecI16x8SubSatS: 2481 c.emit( 2482 NewOperationV128SubSat(ShapeI16x8, true), 2483 ) 2484 case wasm.OpcodeVecI16x8SubSatU: 2485 c.emit( 2486 NewOperationV128SubSat(ShapeI16x8, false), 2487 ) 2488 case wasm.OpcodeVecI16x8Mul: 2489 c.emit( 2490 NewOperationV128Mul(ShapeI16x8), 2491 ) 2492 case wasm.OpcodeVecI32x4Mul: 2493 c.emit( 2494 NewOperationV128Mul(ShapeI32x4), 2495 ) 2496 case wasm.OpcodeVecI64x2Mul: 2497 c.emit( 2498 NewOperationV128Mul(ShapeI64x2), 2499 ) 2500 case wasm.OpcodeVecF32x4Mul: 2501 c.emit( 2502 NewOperationV128Mul(ShapeF32x4), 2503 ) 2504 case wasm.OpcodeVecF64x2Mul: 2505 c.emit( 2506 NewOperationV128Mul(ShapeF64x2), 2507 ) 2508 case wasm.OpcodeVecF32x4Sqrt: 2509 c.emit( 2510 NewOperationV128Sqrt(ShapeF32x4), 2511 ) 2512 case wasm.OpcodeVecF64x2Sqrt: 2513 c.emit( 2514 NewOperationV128Sqrt(ShapeF64x2), 2515 ) 2516 case wasm.OpcodeVecF32x4Div: 2517 c.emit( 2518 NewOperationV128Div(ShapeF32x4), 2519 ) 2520 case wasm.OpcodeVecF64x2Div: 2521 c.emit( 2522 NewOperationV128Div(ShapeF64x2), 2523 ) 2524 case wasm.OpcodeVecI8x16Abs: 2525 c.emit( 2526 NewOperationV128Abs(ShapeI8x16), 2527 ) 2528 case wasm.OpcodeVecI8x16Popcnt: 2529 c.emit( 2530 NewOperationV128Popcnt(ShapeI8x16), 2531 ) 2532 case wasm.OpcodeVecI16x8Abs: 2533 c.emit( 2534 NewOperationV128Abs(ShapeI16x8), 2535 ) 2536 case wasm.OpcodeVecI32x4Abs: 2537 c.emit( 2538 NewOperationV128Abs(ShapeI32x4), 2539 ) 2540 case wasm.OpcodeVecI64x2Abs: 2541 c.emit( 2542 NewOperationV128Abs(ShapeI64x2), 2543 ) 2544 case wasm.OpcodeVecF32x4Abs: 2545 c.emit( 2546 NewOperationV128Abs(ShapeF32x4), 2547 ) 2548 case wasm.OpcodeVecF64x2Abs: 2549 c.emit( 2550 NewOperationV128Abs(ShapeF64x2), 2551 ) 2552 case wasm.OpcodeVecI8x16MinS: 2553 c.emit( 2554 NewOperationV128Min(ShapeI8x16, true), 2555 ) 2556 case wasm.OpcodeVecI8x16MinU: 2557 c.emit( 2558 NewOperationV128Min(ShapeI8x16, false), 2559 ) 2560 case wasm.OpcodeVecI8x16MaxS: 2561 c.emit( 2562 NewOperationV128Max(ShapeI8x16, true), 2563 ) 2564 case wasm.OpcodeVecI8x16MaxU: 2565 c.emit( 2566 NewOperationV128Max(ShapeI8x16, false), 2567 ) 2568 case wasm.OpcodeVecI8x16AvgrU: 2569 c.emit( 2570 NewOperationV128AvgrU(ShapeI8x16), 2571 ) 2572 case wasm.OpcodeVecI16x8MinS: 2573 c.emit( 2574 NewOperationV128Min(ShapeI16x8, true), 2575 ) 2576 case wasm.OpcodeVecI16x8MinU: 2577 c.emit( 2578 NewOperationV128Min(ShapeI16x8, false), 2579 ) 2580 case wasm.OpcodeVecI16x8MaxS: 2581 c.emit( 2582 NewOperationV128Max(ShapeI16x8, true), 2583 ) 2584 case wasm.OpcodeVecI16x8MaxU: 2585 c.emit( 2586 NewOperationV128Max(ShapeI16x8, false), 2587 ) 2588 case wasm.OpcodeVecI16x8AvgrU: 2589 c.emit( 2590 NewOperationV128AvgrU(ShapeI16x8), 2591 ) 2592 case wasm.OpcodeVecI32x4MinS: 2593 c.emit( 2594 NewOperationV128Min(ShapeI32x4, true), 2595 ) 2596 case wasm.OpcodeVecI32x4MinU: 2597 c.emit( 2598 NewOperationV128Min(ShapeI32x4, false), 2599 ) 2600 case wasm.OpcodeVecI32x4MaxS: 2601 c.emit( 2602 NewOperationV128Max(ShapeI32x4, true), 2603 ) 2604 case wasm.OpcodeVecI32x4MaxU: 2605 c.emit( 2606 NewOperationV128Max(ShapeI32x4, false), 2607 ) 2608 case wasm.OpcodeVecF32x4Min: 2609 c.emit( 2610 NewOperationV128Min(ShapeF32x4, false), 2611 ) 2612 case wasm.OpcodeVecF32x4Max: 2613 c.emit( 2614 NewOperationV128Max(ShapeF32x4, false), 2615 ) 2616 case wasm.OpcodeVecF64x2Min: 2617 c.emit( 2618 NewOperationV128Min(ShapeF64x2, false), 2619 ) 2620 case wasm.OpcodeVecF64x2Max: 2621 c.emit( 2622 NewOperationV128Max(ShapeF64x2, false), 2623 ) 2624 case wasm.OpcodeVecF32x4Pmin: 2625 c.emit( 2626 NewOperationV128Pmin(ShapeF32x4), 2627 ) 2628 case wasm.OpcodeVecF32x4Pmax: 2629 c.emit( 2630 NewOperationV128Pmax(ShapeF32x4), 2631 ) 2632 case wasm.OpcodeVecF64x2Pmin: 2633 c.emit( 2634 NewOperationV128Pmin(ShapeF64x2), 2635 ) 2636 case wasm.OpcodeVecF64x2Pmax: 2637 c.emit( 2638 NewOperationV128Pmax(ShapeF64x2), 2639 ) 2640 case wasm.OpcodeVecF32x4Ceil: 2641 c.emit( 2642 NewOperationV128Ceil(ShapeF32x4), 2643 ) 2644 case wasm.OpcodeVecF32x4Floor: 2645 c.emit( 2646 NewOperationV128Floor(ShapeF32x4), 2647 ) 2648 case wasm.OpcodeVecF32x4Trunc: 2649 c.emit( 2650 NewOperationV128Trunc(ShapeF32x4), 2651 ) 2652 case wasm.OpcodeVecF32x4Nearest: 2653 c.emit( 2654 NewOperationV128Nearest(ShapeF32x4), 2655 ) 2656 case wasm.OpcodeVecF64x2Ceil: 2657 c.emit( 2658 NewOperationV128Ceil(ShapeF64x2), 2659 ) 2660 case wasm.OpcodeVecF64x2Floor: 2661 c.emit( 2662 NewOperationV128Floor(ShapeF64x2), 2663 ) 2664 case wasm.OpcodeVecF64x2Trunc: 2665 c.emit( 2666 NewOperationV128Trunc(ShapeF64x2), 2667 ) 2668 case wasm.OpcodeVecF64x2Nearest: 2669 c.emit( 2670 NewOperationV128Nearest(ShapeF64x2), 2671 ) 2672 case wasm.OpcodeVecI16x8ExtendLowI8x16S: 2673 c.emit( 2674 NewOperationV128Extend(ShapeI8x16, true, true), 2675 ) 2676 case wasm.OpcodeVecI16x8ExtendHighI8x16S: 2677 c.emit( 2678 NewOperationV128Extend(ShapeI8x16, true, false), 2679 ) 2680 case wasm.OpcodeVecI16x8ExtendLowI8x16U: 2681 c.emit( 2682 NewOperationV128Extend(ShapeI8x16, false, true), 2683 ) 2684 case wasm.OpcodeVecI16x8ExtendHighI8x16U: 2685 c.emit( 2686 NewOperationV128Extend(ShapeI8x16, false, false), 2687 ) 2688 case wasm.OpcodeVecI32x4ExtendLowI16x8S: 2689 c.emit( 2690 NewOperationV128Extend(ShapeI16x8, true, true), 2691 ) 2692 case wasm.OpcodeVecI32x4ExtendHighI16x8S: 2693 c.emit( 2694 NewOperationV128Extend(ShapeI16x8, true, false), 2695 ) 2696 case wasm.OpcodeVecI32x4ExtendLowI16x8U: 2697 c.emit( 2698 NewOperationV128Extend(ShapeI16x8, false, true), 2699 ) 2700 case wasm.OpcodeVecI32x4ExtendHighI16x8U: 2701 c.emit( 2702 NewOperationV128Extend(ShapeI16x8, false, false), 2703 ) 2704 case wasm.OpcodeVecI64x2ExtendLowI32x4S: 2705 c.emit( 2706 NewOperationV128Extend(ShapeI32x4, true, true), 2707 ) 2708 case wasm.OpcodeVecI64x2ExtendHighI32x4S: 2709 c.emit( 2710 NewOperationV128Extend(ShapeI32x4, true, false), 2711 ) 2712 case wasm.OpcodeVecI64x2ExtendLowI32x4U: 2713 c.emit( 2714 NewOperationV128Extend(ShapeI32x4, false, true), 2715 ) 2716 case wasm.OpcodeVecI64x2ExtendHighI32x4U: 2717 c.emit( 2718 NewOperationV128Extend(ShapeI32x4, false, false), 2719 ) 2720 case wasm.OpcodeVecI16x8Q15mulrSatS: 2721 c.emit( 2722 NewOperationV128Q15mulrSatS(), 2723 ) 2724 case wasm.OpcodeVecI16x8ExtMulLowI8x16S: 2725 c.emit( 2726 NewOperationV128ExtMul(ShapeI8x16, true, true), 2727 ) 2728 case wasm.OpcodeVecI16x8ExtMulHighI8x16S: 2729 c.emit( 2730 NewOperationV128ExtMul(ShapeI8x16, true, false), 2731 ) 2732 case wasm.OpcodeVecI16x8ExtMulLowI8x16U: 2733 c.emit( 2734 NewOperationV128ExtMul(ShapeI8x16, false, true), 2735 ) 2736 case wasm.OpcodeVecI16x8ExtMulHighI8x16U: 2737 c.emit( 2738 NewOperationV128ExtMul(ShapeI8x16, false, false), 2739 ) 2740 case wasm.OpcodeVecI32x4ExtMulLowI16x8S: 2741 c.emit( 2742 NewOperationV128ExtMul(ShapeI16x8, true, true), 2743 ) 2744 case wasm.OpcodeVecI32x4ExtMulHighI16x8S: 2745 c.emit( 2746 NewOperationV128ExtMul(ShapeI16x8, true, false), 2747 ) 2748 case wasm.OpcodeVecI32x4ExtMulLowI16x8U: 2749 c.emit( 2750 NewOperationV128ExtMul(ShapeI16x8, false, true), 2751 ) 2752 case wasm.OpcodeVecI32x4ExtMulHighI16x8U: 2753 c.emit( 2754 NewOperationV128ExtMul(ShapeI16x8, false, false), 2755 ) 2756 case wasm.OpcodeVecI64x2ExtMulLowI32x4S: 2757 c.emit( 2758 NewOperationV128ExtMul(ShapeI32x4, true, true), 2759 ) 2760 case wasm.OpcodeVecI64x2ExtMulHighI32x4S: 2761 c.emit( 2762 NewOperationV128ExtMul(ShapeI32x4, true, false), 2763 ) 2764 case wasm.OpcodeVecI64x2ExtMulLowI32x4U: 2765 c.emit( 2766 NewOperationV128ExtMul(ShapeI32x4, false, true), 2767 ) 2768 case wasm.OpcodeVecI64x2ExtMulHighI32x4U: 2769 c.emit( 2770 NewOperationV128ExtMul(ShapeI32x4, false, false), 2771 ) 2772 case wasm.OpcodeVecI16x8ExtaddPairwiseI8x16S: 2773 c.emit( 2774 NewOperationV128ExtAddPairwise(ShapeI8x16, true), 2775 ) 2776 case wasm.OpcodeVecI16x8ExtaddPairwiseI8x16U: 2777 c.emit( 2778 NewOperationV128ExtAddPairwise(ShapeI8x16, false), 2779 ) 2780 case wasm.OpcodeVecI32x4ExtaddPairwiseI16x8S: 2781 c.emit( 2782 NewOperationV128ExtAddPairwise(ShapeI16x8, true), 2783 ) 2784 case wasm.OpcodeVecI32x4ExtaddPairwiseI16x8U: 2785 c.emit( 2786 NewOperationV128ExtAddPairwise(ShapeI16x8, false), 2787 ) 2788 case wasm.OpcodeVecF64x2PromoteLowF32x4Zero: 2789 c.emit( 2790 NewOperationV128FloatPromote(), 2791 ) 2792 case wasm.OpcodeVecF32x4DemoteF64x2Zero: 2793 c.emit( 2794 NewOperationV128FloatDemote(), 2795 ) 2796 case wasm.OpcodeVecF32x4ConvertI32x4S: 2797 c.emit( 2798 NewOperationV128FConvertFromI(ShapeF32x4, true), 2799 ) 2800 case wasm.OpcodeVecF32x4ConvertI32x4U: 2801 c.emit( 2802 NewOperationV128FConvertFromI(ShapeF32x4, false), 2803 ) 2804 case wasm.OpcodeVecF64x2ConvertLowI32x4S: 2805 c.emit( 2806 NewOperationV128FConvertFromI(ShapeF64x2, true), 2807 ) 2808 case wasm.OpcodeVecF64x2ConvertLowI32x4U: 2809 c.emit( 2810 NewOperationV128FConvertFromI(ShapeF64x2, false), 2811 ) 2812 case wasm.OpcodeVecI32x4DotI16x8S: 2813 c.emit( 2814 NewOperationV128Dot(), 2815 ) 2816 case wasm.OpcodeVecI8x16NarrowI16x8S: 2817 c.emit( 2818 NewOperationV128Narrow(ShapeI16x8, true), 2819 ) 2820 case wasm.OpcodeVecI8x16NarrowI16x8U: 2821 c.emit( 2822 NewOperationV128Narrow(ShapeI16x8, false), 2823 ) 2824 case wasm.OpcodeVecI16x8NarrowI32x4S: 2825 c.emit( 2826 NewOperationV128Narrow(ShapeI32x4, true), 2827 ) 2828 case wasm.OpcodeVecI16x8NarrowI32x4U: 2829 c.emit( 2830 NewOperationV128Narrow(ShapeI32x4, false), 2831 ) 2832 case wasm.OpcodeVecI32x4TruncSatF32x4S: 2833 c.emit( 2834 NewOperationV128ITruncSatFromF(ShapeF32x4, true), 2835 ) 2836 case wasm.OpcodeVecI32x4TruncSatF32x4U: 2837 c.emit( 2838 NewOperationV128ITruncSatFromF(ShapeF32x4, false), 2839 ) 2840 case wasm.OpcodeVecI32x4TruncSatF64x2SZero: 2841 c.emit( 2842 NewOperationV128ITruncSatFromF(ShapeF64x2, true), 2843 ) 2844 case wasm.OpcodeVecI32x4TruncSatF64x2UZero: 2845 c.emit( 2846 NewOperationV128ITruncSatFromF(ShapeF64x2, false), 2847 ) 2848 default: 2849 return fmt.Errorf("unsupported vector instruction in wazeroir: %s", wasm.VectorInstructionName(vecOp)) 2850 } 2851 default: 2852 return fmt.Errorf("unsupported instruction in wazeroir: 0x%x", op) 2853 } 2854 2855 // Move the program counter to point to the next instruction. 2856 c.pc++ 2857 return nil 2858 } 2859 2860 func (c *Compiler) nextFrameID() (id uint32) { 2861 id = c.currentFrameID + 1 2862 c.currentFrameID++ 2863 return 2864 } 2865 2866 func (c *Compiler) applyToStack(opcode wasm.Opcode) (index uint32, err error) { 2867 switch opcode { 2868 case 2869 // These are the opcodes that is coupled with "index" immediate 2870 // and it DOES affect the signature of opcode. 2871 wasm.OpcodeCall, 2872 wasm.OpcodeCallIndirect, 2873 wasm.OpcodeLocalGet, 2874 wasm.OpcodeLocalSet, 2875 wasm.OpcodeLocalTee, 2876 wasm.OpcodeGlobalGet, 2877 wasm.OpcodeGlobalSet: 2878 // Assumes that we are at the opcode now so skip it before read immediates. 2879 v, num, err := leb128.LoadUint32(c.body[c.pc+1:]) 2880 if err != nil { 2881 return 0, fmt.Errorf("reading immediates: %w", err) 2882 } 2883 c.pc += num 2884 index = v 2885 default: 2886 // Note that other opcodes are free of index 2887 // as it doesn't affect the signature of opt code. 2888 // In other words, the "index" argument of wasmOpcodeSignature 2889 // is ignored there. 2890 } 2891 2892 if c.unreachableState.on { 2893 return 0, nil 2894 } 2895 2896 // Retrieve the signature of the opcode. 2897 s, err := c.wasmOpcodeSignature(opcode, index) 2898 if err != nil { 2899 return 0, err 2900 } 2901 2902 // Manipulate the stack according to the signature. 2903 // Note that the following algorithm assumes that 2904 // the unknown type is unique in the signature, 2905 // and is determined by the actual type on the stack. 2906 // The determined type is stored in this typeParam. 2907 var typeParam UnsignedType 2908 var typeParamFound bool 2909 for i := range s.in { 2910 want := s.in[len(s.in)-1-i] 2911 actual := c.stackPop() 2912 if want == UnsignedTypeUnknown && typeParamFound { 2913 want = typeParam 2914 } else if want == UnsignedTypeUnknown { 2915 want = actual 2916 typeParam = want 2917 typeParamFound = true 2918 } 2919 if want != actual { 2920 return 0, fmt.Errorf("input signature mismatch: want %s but have %s", want, actual) 2921 } 2922 } 2923 2924 for _, target := range s.out { 2925 if target == UnsignedTypeUnknown && !typeParamFound { 2926 return 0, fmt.Errorf("cannot determine type of unknown result") 2927 } else if target == UnsignedTypeUnknown { 2928 c.stackPush(typeParam) 2929 } else { 2930 c.stackPush(target) 2931 } 2932 } 2933 2934 return index, nil 2935 } 2936 2937 func (c *Compiler) stackPeek() (ret UnsignedType) { 2938 ret = c.stack[len(c.stack)-1] 2939 return 2940 } 2941 2942 func (c *Compiler) stackPop() (ret UnsignedType) { 2943 // No need to check stack bound 2944 // as we can assume that all the operations 2945 // are valid thanks to validateFunction 2946 // at module validation phase. 2947 ret = c.stack[len(c.stack)-1] 2948 c.stack = c.stack[:len(c.stack)-1] 2949 return 2950 } 2951 2952 func (c *Compiler) stackPush(ts UnsignedType) { 2953 c.stack = append(c.stack, ts) 2954 } 2955 2956 // emit adds the operations into the result. 2957 func (c *Compiler) emit(op UnionOperation) { 2958 if !c.unreachableState.on { 2959 switch op.Kind { 2960 case OperationKindDrop: 2961 // If the drop range is nil, 2962 // we could remove such operations. 2963 // That happens when drop operation is unnecessary. 2964 // i.e. when there's no need to adjust stack before jmp. 2965 if int64(op.U1) == -1 { 2966 return 2967 } 2968 } 2969 c.result.Operations = append(c.result.Operations, op) 2970 if c.needSourceOffset { 2971 c.result.IROperationSourceOffsetsInWasmBinary = append(c.result.IROperationSourceOffsetsInWasmBinary, 2972 c.currentOpPC+c.bodyOffsetInCodeSection) 2973 } 2974 } 2975 } 2976 2977 // Emit const expression with default values of the given type. 2978 func (c *Compiler) emitDefaultValue(t wasm.ValueType) { 2979 switch t { 2980 case wasm.ValueTypeI32: 2981 c.stackPush(UnsignedTypeI32) 2982 c.emit(NewOperationConstI32(0)) 2983 case wasm.ValueTypeI64, wasm.ValueTypeExternref, wasm.ValueTypeFuncref: 2984 c.stackPush(UnsignedTypeI64) 2985 c.emit(NewOperationConstI64(0)) 2986 case wasm.ValueTypeF32: 2987 c.stackPush(UnsignedTypeF32) 2988 c.emit(NewOperationConstF32(0)) 2989 case wasm.ValueTypeF64: 2990 c.stackPush(UnsignedTypeF64) 2991 c.emit(NewOperationConstF64(0)) 2992 case wasm.ValueTypeV128: 2993 c.stackPush(UnsignedTypeV128) 2994 c.emit(NewOperationV128Const(0, 0)) 2995 } 2996 } 2997 2998 // Returns the "depth" (starting from top of the stack) 2999 // of the n-th local. 3000 func (c *Compiler) localDepth(index wasm.Index) int { 3001 height := c.localIndexToStackHeightInUint64[index] 3002 return c.stackLenInUint64(len(c.stack)) - 1 - int(height) 3003 } 3004 3005 func (c *Compiler) localType(index wasm.Index) (t wasm.ValueType) { 3006 if params := uint32(len(c.sig.Params)); index < params { 3007 t = c.sig.Params[index] 3008 } else { 3009 t = c.localTypes[index-params] 3010 } 3011 return 3012 } 3013 3014 // getFrameDropRange returns the range (starting from top of the stack) that spans across the (uint64) stack. The range is 3015 // supposed to be dropped from the stack when the given frame exists or branch into it. 3016 // 3017 // * frame is the control frame which the call-site is trying to branch into or exit. 3018 // * isEnd true if the call-site is handling wasm.OpcodeEnd. 3019 func (c *Compiler) getFrameDropRange(frame *controlFrame, isEnd bool) InclusiveRange { 3020 var start int 3021 if !isEnd && frame.kind == controlFrameKindLoop { 3022 // If this is not End and the call-site is trying to branch into the Loop control frame, 3023 // we have to Start executing from the beginning of the loop block. 3024 // Therefore, we have to pass the inputs to the frame. 3025 start = frame.blockType.ParamNumInUint64 3026 } else { 3027 start = frame.blockType.ResultNumInUint64 3028 } 3029 var end int 3030 if frame.kind == controlFrameKindFunction { 3031 // On the function return, we eliminate all the contents on the stack 3032 // including locals (existing below of frame.originalStackLen) 3033 end = c.stackLenInUint64(len(c.stack)) - 1 3034 } else { 3035 end = c.stackLenInUint64(len(c.stack)) - 1 - c.stackLenInUint64(frame.originalStackLenWithoutParam) 3036 } 3037 if start <= end { 3038 return InclusiveRange{Start: int32(start), End: int32(end)} 3039 } else { 3040 return NopInclusiveRange 3041 } 3042 } 3043 3044 func (c *Compiler) stackLenInUint64(ceil int) (ret int) { 3045 for i := 0; i < ceil; i++ { 3046 if c.stack[i] == UnsignedTypeV128 { 3047 ret += 2 3048 } else { 3049 ret++ 3050 } 3051 } 3052 return 3053 } 3054 3055 func (c *Compiler) readMemoryArg(tag string) (MemoryArg, error) { 3056 c.result.UsesMemory = true 3057 alignment, num, err := leb128.LoadUint32(c.body[c.pc+1:]) 3058 if err != nil { 3059 return MemoryArg{}, fmt.Errorf("reading alignment for %s: %w", tag, err) 3060 } 3061 c.pc += num 3062 offset, num, err := leb128.LoadUint32(c.body[c.pc+1:]) 3063 if err != nil { 3064 return MemoryArg{}, fmt.Errorf("reading offset for %s: %w", tag, err) 3065 } 3066 c.pc += num 3067 return MemoryArg{Offset: offset, Alignment: alignment}, nil 3068 }