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