github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/engine/wazevo/ssa/instructions.go (about)

     1  package ssa
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"strings"
     7  
     8  	"github.com/bananabytelabs/wazero/internal/engine/wazevo/wazevoapi"
     9  )
    10  
    11  // Opcode represents a SSA instruction.
    12  type Opcode uint32
    13  
    14  // Instruction represents an instruction whose opcode is specified by
    15  // Opcode. Since Go doesn't have union type, we use this flattened type
    16  // for all instructions, and therefore each field has different meaning
    17  // depending on Opcode.
    18  type Instruction struct {
    19  	// id is the unique ID of this instruction which ascends from 0 following the order of program.
    20  	id         int
    21  	opcode     Opcode
    22  	u1, u2     uint64
    23  	v          Value
    24  	v2         Value
    25  	v3         Value
    26  	vs         []Value
    27  	typ        Type
    28  	blk        BasicBlock
    29  	targets    []BasicBlock
    30  	prev, next *Instruction
    31  
    32  	rValue         Value
    33  	rValues        []Value
    34  	gid            InstructionGroupID
    35  	sourceOffset   SourceOffset
    36  	live           bool
    37  	alreadyLowered bool
    38  }
    39  
    40  // SourceOffset represents the offset of the source of an instruction.
    41  type SourceOffset int64
    42  
    43  const sourceOffsetUnknown = -1
    44  
    45  // Valid returns true if this source offset is valid.
    46  func (l SourceOffset) Valid() bool {
    47  	return l != sourceOffsetUnknown
    48  }
    49  
    50  func (i *Instruction) annotateSourceOffset(line SourceOffset) {
    51  	i.sourceOffset = line
    52  }
    53  
    54  // SourceOffset returns the source offset of this instruction.
    55  func (i *Instruction) SourceOffset() SourceOffset {
    56  	return i.sourceOffset
    57  }
    58  
    59  // Opcode returns the opcode of this instruction.
    60  func (i *Instruction) Opcode() Opcode {
    61  	return i.opcode
    62  }
    63  
    64  // GroupID returns the InstructionGroupID of this instruction.
    65  func (i *Instruction) GroupID() InstructionGroupID {
    66  	return i.gid
    67  }
    68  
    69  // MarkLowered marks this instruction as already lowered.
    70  func (i *Instruction) MarkLowered() {
    71  	i.alreadyLowered = true
    72  }
    73  
    74  // Lowered returns true if this instruction is already lowered.
    75  func (i *Instruction) Lowered() bool {
    76  	return i.alreadyLowered
    77  }
    78  
    79  // resetInstruction resets this instruction to the initial state.
    80  func resetInstruction(i *Instruction) {
    81  	*i = Instruction{}
    82  	i.v = ValueInvalid
    83  	i.v2 = ValueInvalid
    84  	i.v3 = ValueInvalid
    85  	i.rValue = ValueInvalid
    86  	i.typ = typeInvalid
    87  	i.vs = nil
    88  	i.sourceOffset = sourceOffsetUnknown
    89  }
    90  
    91  // InstructionGroupID is assigned to each instruction and represents a group of instructions
    92  // where each instruction is interchangeable with others except for the last instruction
    93  // in the group which has side effects. In short, InstructionGroupID is determined by the side effects of instructions.
    94  // That means, if there's an instruction with side effect between two instructions, then these two instructions
    95  // will have different instructionGroupID. Note that each block always ends with branching, which is with side effects,
    96  // therefore, instructions in different blocks always have different InstructionGroupID(s).
    97  //
    98  // The notable application of this is used in lowering SSA-level instruction to a ISA specific instruction,
    99  // where we eagerly try to merge multiple instructions into single operation etc. Such merging cannot be done
   100  // if these instruction have different InstructionGroupID since it will change the semantics of a program.
   101  //
   102  // See passDeadCodeElimination.
   103  type InstructionGroupID uint32
   104  
   105  // Returns Value(s) produced by this instruction if any.
   106  // The `first` is the first return value, and `rest` is the rest of the values.
   107  func (i *Instruction) Returns() (first Value, rest []Value) {
   108  	return i.rValue, i.rValues
   109  }
   110  
   111  // Return returns a Value(s) produced by this instruction if any.
   112  // If there's multiple return values, only the first one is returned.
   113  func (i *Instruction) Return() (first Value) {
   114  	return i.rValue
   115  }
   116  
   117  // Args returns the arguments to this instruction.
   118  func (i *Instruction) Args() (v1, v2, v3 Value, vs []Value) {
   119  	return i.v, i.v2, i.v3, i.vs
   120  }
   121  
   122  // Arg returns the first argument to this instruction.
   123  func (i *Instruction) Arg() Value {
   124  	return i.v
   125  }
   126  
   127  // Arg2 returns the first two arguments to this instruction.
   128  func (i *Instruction) Arg2() (Value, Value) {
   129  	return i.v, i.v2
   130  }
   131  
   132  // ArgWithLane returns the first argument to this instruction, and the lane type.
   133  func (i *Instruction) ArgWithLane() (Value, VecLane) {
   134  	return i.v, VecLane(i.u1)
   135  }
   136  
   137  // Arg2WithLane returns the first two arguments to this instruction, and the lane type.
   138  func (i *Instruction) Arg2WithLane() (Value, Value, VecLane) {
   139  	return i.v, i.v2, VecLane(i.u1)
   140  }
   141  
   142  // ShuffleData returns the first two arguments to this instruction and 2 uint64s `lo`, `hi`.
   143  //
   144  // Note: Each uint64 encodes a sequence of 8 bytes where each byte encodes a VecLane,
   145  // so that the 128bit integer `hi<<64|lo` packs a slice `[16]VecLane`,
   146  // where `lane[0]` is the least significant byte, and `lane[n]` is shifted to offset `n*8`.
   147  func (i *Instruction) ShuffleData() (v Value, v2 Value, lo uint64, hi uint64) {
   148  	return i.v, i.v2, i.u1, i.u2
   149  }
   150  
   151  // Arg3 returns the first three arguments to this instruction.
   152  func (i *Instruction) Arg3() (Value, Value, Value) {
   153  	return i.v, i.v2, i.v3
   154  }
   155  
   156  // Next returns the next instruction laid out next to itself.
   157  func (i *Instruction) Next() *Instruction {
   158  	return i.next
   159  }
   160  
   161  // Prev returns the previous instruction laid out prior to itself.
   162  func (i *Instruction) Prev() *Instruction {
   163  	return i.prev
   164  }
   165  
   166  // IsBranching returns true if this instruction is a branching instruction.
   167  func (i *Instruction) IsBranching() bool {
   168  	switch i.opcode {
   169  	case OpcodeJump, OpcodeBrz, OpcodeBrnz, OpcodeBrTable:
   170  		return true
   171  	default:
   172  		return false
   173  	}
   174  }
   175  
   176  // TODO: complete opcode comments.
   177  const (
   178  	OpcodeInvalid Opcode = iota
   179  
   180  	// OpcodeUndefined is a placeholder for undefined opcode. This can be used for debugging to intentionally
   181  	// cause a crash at certain point.
   182  	OpcodeUndefined
   183  
   184  	// OpcodeJump takes the list of args to the `block` and unconditionally jumps to it.
   185  	OpcodeJump
   186  
   187  	// OpcodeBrz branches into `blk` with `args`  if the value `c` equals zero: `Brz c, blk, args`.
   188  	OpcodeBrz
   189  
   190  	// OpcodeBrnz branches into `blk` with `args`  if the value `c` is not zero: `Brnz c, blk, args`.
   191  	OpcodeBrnz
   192  
   193  	// OpcodeBrTable takes the index value `index`, and branches into `labelX`. If the `index` is out of range,
   194  	// it branches into the last labelN: `BrTable index, [label1, label2, ... labelN]`.
   195  	OpcodeBrTable
   196  
   197  	// OpcodeExitWithCode exit the execution immediately.
   198  	OpcodeExitWithCode
   199  
   200  	// OpcodeExitIfTrueWithCode exits the execution immediately if the value `c` is not zero.
   201  	OpcodeExitIfTrueWithCode
   202  
   203  	// OpcodeReturn returns from the function: `return rvalues`.
   204  	OpcodeReturn
   205  
   206  	// OpcodeCall calls a function specified by the symbol FN with arguments `args`: `returnvals = Call FN, args...`
   207  	// This is a "near" call, which means the call target is known at compile time, and the target is relatively close
   208  	// to this function. If the target cannot be reached by near call, the backend fails to compile.
   209  	OpcodeCall
   210  
   211  	// OpcodeCallIndirect calls a function specified by `callee` which is a function address: `returnvals = call_indirect SIG, callee, args`.
   212  	// Note that this is different from call_indirect in Wasm, which also does type checking, etc.
   213  	OpcodeCallIndirect
   214  
   215  	// OpcodeSplat performs a vector splat operation: `v = Splat.lane x`.
   216  	OpcodeSplat
   217  
   218  	// OpcodeSwizzle performs a vector swizzle operation: `v = Swizzle.lane x, y`.
   219  	OpcodeSwizzle
   220  
   221  	// OpcodeInsertlane ...
   222  	// `v = insertlane x, y, Idx`. (TernaryImm8)
   223  	OpcodeInsertlane
   224  
   225  	// OpcodeExtractlane ...
   226  	// `v = extractlane x, Idx`. (BinaryImm8)
   227  	OpcodeExtractlane
   228  
   229  	// OpcodeLoad loads a Type value from the [base + offset] address: `v = Load base, offset`.
   230  	OpcodeLoad
   231  
   232  	// OpcodeStore stores a Type value to the [base + offset] address: `Store v, base, offset`.
   233  	OpcodeStore
   234  
   235  	// OpcodeUload8 loads the 8-bit value from the [base + offset] address, zero-extended to 64 bits: `v = Uload8 base, offset`.
   236  	OpcodeUload8
   237  
   238  	// OpcodeSload8 loads the 8-bit value from the [base + offset] address, sign-extended to 64 bits: `v = Sload8 base, offset`.
   239  	OpcodeSload8
   240  
   241  	// OpcodeIstore8 stores the 8-bit value to the [base + offset] address, sign-extended to 64 bits: `Istore8 v, base, offset`.
   242  	OpcodeIstore8
   243  
   244  	// OpcodeUload16 loads the 16-bit value from the [base + offset] address, zero-extended to 64 bits: `v = Uload16 base, offset`.
   245  	OpcodeUload16
   246  
   247  	// OpcodeSload16 loads the 16-bit value from the [base + offset] address, sign-extended to 64 bits: `v = Sload16 base, offset`.
   248  	OpcodeSload16
   249  
   250  	// OpcodeIstore16 stores the 16-bit value to the [base + offset] address, zero-extended to 64 bits: `Istore16 v, base, offset`.
   251  	OpcodeIstore16
   252  
   253  	// OpcodeUload32 loads the 32-bit value from the [base + offset] address, zero-extended to 64 bits: `v = Uload32 base, offset`.
   254  	OpcodeUload32
   255  
   256  	// OpcodeSload32 loads the 32-bit value from the [base + offset] address, sign-extended to 64 bits: `v = Sload32 base, offset`.
   257  	OpcodeSload32
   258  
   259  	// OpcodeIstore32 stores the 32-bit value to the [base + offset] address, zero-extended to 64 bits: `Istore16 v, base, offset`.
   260  	OpcodeIstore32
   261  
   262  	// OpcodeLoadSplat represents a load that replicates the loaded value to all lanes `v = LoadSplat.lane p, Offset`.
   263  	OpcodeLoadSplat
   264  
   265  	// OpcodeVZeroExtLoad loads a scalar single/double precision floating point value from the [p + Offset] address,
   266  	// and zero-extend it to the V128 value: `v = VExtLoad  p, Offset`.
   267  	OpcodeVZeroExtLoad
   268  
   269  	// OpcodeIconst represents the integer const.
   270  	OpcodeIconst
   271  
   272  	// OpcodeF32const represents the single-precision const.
   273  	OpcodeF32const
   274  
   275  	// OpcodeF64const represents the double-precision const.
   276  	OpcodeF64const
   277  
   278  	// OpcodeVconst represents the 128bit vector const.
   279  	OpcodeVconst
   280  
   281  	// OpcodeVbor computes binary or between two 128bit vectors: `v = bor x, y`.
   282  	OpcodeVbor
   283  
   284  	// OpcodeVbxor computes binary xor between two 128bit vectors: `v = bxor x, y`.
   285  	OpcodeVbxor
   286  
   287  	// OpcodeVband computes binary and between two 128bit vectors: `v = band x, y`.
   288  	OpcodeVband
   289  
   290  	// OpcodeVbandnot computes binary and-not between two 128bit vectors: `v = bandnot x, y`.
   291  	OpcodeVbandnot
   292  
   293  	// OpcodeVbnot negates a 128bit vector: `v = bnot x`.
   294  	OpcodeVbnot
   295  
   296  	// OpcodeVbitselect uses the bits in the control mask c to select the corresponding bit from x when 1
   297  	// and y when 0: `v = bitselect c, x, y`.
   298  	OpcodeVbitselect
   299  
   300  	// OpcodeShuffle shuffles two vectors using the given 128-bit immediate: `v = shuffle imm, x, y`.
   301  	// For each byte in the immediate, a value i in [0, 15] selects the i-th byte in vector x;
   302  	// i in [16, 31] selects the (i-16)-th byte in vector y.
   303  	OpcodeShuffle
   304  
   305  	// OpcodeSelect chooses between two values based on a condition `c`: `v = Select c, x, y`.
   306  	OpcodeSelect
   307  
   308  	// OpcodeVanyTrue performs a any true operation: `s = VanyTrue a`.
   309  	OpcodeVanyTrue
   310  
   311  	// OpcodeVallTrue performs a lane-wise all true operation: `s = VallTrue.lane a`.
   312  	OpcodeVallTrue
   313  
   314  	// OpcodeVhighBits performs a lane-wise extract of the high bits: `v = VhighBits.lane a`.
   315  	OpcodeVhighBits
   316  
   317  	// OpcodeIcmp compares two integer values with the given condition: `v = icmp Cond, x, y`.
   318  	OpcodeIcmp
   319  
   320  	// OpcodeVIcmp compares two integer values with the given condition: `v = vicmp Cond, x, y` on vector.
   321  	OpcodeVIcmp
   322  
   323  	// OpcodeIcmpImm compares an integer value with the immediate value on the given condition: `v = icmp_imm Cond, x, Y`.
   324  	OpcodeIcmpImm
   325  
   326  	// OpcodeIadd performs an integer addition: `v = Iadd x, y`.
   327  	OpcodeIadd
   328  
   329  	// OpcodeVIadd performs an integer addition: `v = VIadd.lane x, y` on vector.
   330  	OpcodeVIadd
   331  
   332  	// OpcodeVSaddSat performs a signed saturating vector addition: `v = VSaddSat.lane x, y` on vector.
   333  	OpcodeVSaddSat
   334  
   335  	// OpcodeVUaddSat performs an unsigned saturating vector addition: `v = VUaddSat.lane x, y` on vector.
   336  	OpcodeVUaddSat
   337  
   338  	// OpcodeIsub performs an integer subtraction: `v = Isub x, y`.
   339  	OpcodeIsub
   340  
   341  	// OpcodeVIsub performs an integer subtraction: `v = VIsub.lane x, y` on vector.
   342  	OpcodeVIsub
   343  
   344  	// OpcodeVSsubSat performs a signed saturating vector subtraction: `v = VSsubSat.lane x, y` on vector.
   345  	OpcodeVSsubSat
   346  
   347  	// OpcodeVUsubSat performs an unsigned saturating vector subtraction: `v = VUsubSat.lane x, y` on vector.
   348  	OpcodeVUsubSat
   349  
   350  	// OpcodeVImin performs a signed integer min: `v = VImin.lane x, y` on vector.
   351  	OpcodeVImin
   352  
   353  	// OpcodeVUmin performs an unsigned integer min: `v = VUmin.lane x, y` on vector.
   354  	OpcodeVUmin
   355  
   356  	// OpcodeVImax performs a signed integer max: `v = VImax.lane x, y` on vector.
   357  	OpcodeVImax
   358  
   359  	// OpcodeVUmax performs an unsigned integer max: `v = VUmax.lane x, y` on vector.
   360  	OpcodeVUmax
   361  
   362  	// OpcodeVAvgRound performs an unsigned integer avg, truncating to zero: `v = VAvgRound.lane x, y` on vector.
   363  	OpcodeVAvgRound
   364  
   365  	// OpcodeVImul performs an integer multiplication: `v = VImul.lane x, y` on vector.
   366  	OpcodeVImul
   367  
   368  	// OpcodeVIneg negates the given integer vector value: `v = VIneg x`.
   369  	OpcodeVIneg
   370  
   371  	// OpcodeVIpopcnt counts the number of 1-bits in the given vector: `v = VIpopcnt x`.
   372  	OpcodeVIpopcnt
   373  
   374  	// OpcodeVIabs returns the absolute value for the given vector value: `v = VIabs.lane x`.
   375  	OpcodeVIabs
   376  
   377  	// OpcodeVIshl shifts x left by (y mod lane-width): `v = VIshl.lane x, y` on vector.
   378  	OpcodeVIshl
   379  
   380  	// OpcodeVUshr shifts x right by (y mod lane-width), unsigned: `v = VUshr.lane x, y` on vector.
   381  	OpcodeVUshr
   382  
   383  	// OpcodeVSshr shifts x right by (y mod lane-width), signed: `v = VSshr.lane x, y` on vector.
   384  	OpcodeVSshr
   385  
   386  	// OpcodeVFabs takes the absolute value of a floating point value: `v = VFabs.lane x on vector.
   387  	OpcodeVFabs
   388  
   389  	// OpcodeVFmax takes the maximum of two floating point values: `v = VFmax.lane x, y on vector.
   390  	OpcodeVFmax
   391  
   392  	// OpcodeVFmin takes the minimum of two floating point values: `v = VFmin.lane x, y on vector.
   393  	OpcodeVFmin
   394  
   395  	// OpcodeVFneg negates the given floating point vector value: `v = VFneg x`.
   396  	OpcodeVFneg
   397  
   398  	// OpcodeVFadd performs a floating point addition: `v = VFadd.lane x, y` on vector.
   399  	OpcodeVFadd
   400  
   401  	// OpcodeVFsub performs a floating point subtraction: `v = VFsub.lane x, y` on vector.
   402  	OpcodeVFsub
   403  
   404  	// OpcodeVFmul performs a floating point multiplication: `v = VFmul.lane x, y` on vector.
   405  	OpcodeVFmul
   406  
   407  	// OpcodeVFdiv performs a floating point division: `v = VFdiv.lane x, y` on vector.
   408  	OpcodeVFdiv
   409  
   410  	// OpcodeVFcmp compares two float values with the given condition: `v = VFcmp.lane Cond, x, y` on float.
   411  	OpcodeVFcmp
   412  
   413  	// OpcodeVCeil takes the ceiling of the given floating point value: `v = ceil.lane x` on vector.
   414  	OpcodeVCeil
   415  
   416  	// OpcodeVFloor takes the floor of the given floating point value: `v = floor.lane x` on vector.
   417  	OpcodeVFloor
   418  
   419  	// OpcodeVTrunc takes the truncation of the given floating point value: `v = trunc.lane x` on vector.
   420  	OpcodeVTrunc
   421  
   422  	// OpcodeVNearest takes the nearest integer of the given floating point value: `v = nearest.lane x` on vector.
   423  	OpcodeVNearest
   424  
   425  	// OpcodeVMaxPseudo computes the lane-wise maximum value `v = VMaxPseudo.lane x, y` on vector defined as `x < y ? x : y`.
   426  	OpcodeVMaxPseudo
   427  
   428  	// OpcodeVMinPseudo computes the lane-wise minimum value `v = VMinPseudo.lane x, y` on vector defined as `y < x ? x : y`.
   429  	OpcodeVMinPseudo
   430  
   431  	// OpcodeVSqrt takes the minimum of two floating point values: `v = VFmin.lane x, y` on vector.
   432  	OpcodeVSqrt
   433  
   434  	// OpcodeVFcvtToUintSat converts a floating point value to an unsigned integer: `v = FcvtToUintSat.lane x` on vector.
   435  	OpcodeVFcvtToUintSat
   436  
   437  	// OpcodeVFcvtToSintSat converts a floating point value to a signed integer: `v = VFcvtToSintSat.lane x` on vector.
   438  	OpcodeVFcvtToSintSat
   439  
   440  	// OpcodeVFcvtFromUint converts a floating point value from an unsigned integer: `v = FcvtFromUint.lane x` on vector.
   441  	OpcodeVFcvtFromUint
   442  
   443  	// OpcodeVFcvtFromSint converts a floating point value from a signed integer: `v = VFcvtFromSint.lane x` on vector.
   444  	OpcodeVFcvtFromSint
   445  
   446  	// OpcodeImul performs an integer multiplication: `v = Imul x, y`.
   447  	OpcodeImul
   448  
   449  	// OpcodeUdiv performs the unsigned integer division `v = Udiv x, y`.
   450  	OpcodeUdiv
   451  
   452  	// OpcodeSdiv performs the signed integer division `v = Sdiv x, y`.
   453  	OpcodeSdiv
   454  
   455  	// OpcodeUrem computes the remainder of the unsigned integer division `v = Urem x, y`.
   456  	OpcodeUrem
   457  
   458  	// OpcodeSrem computes the remainder of the signed integer division `v = Srem x, y`.
   459  	OpcodeSrem
   460  
   461  	// OpcodeBand performs a binary and: `v = Band x, y`.
   462  	OpcodeBand
   463  
   464  	// OpcodeBor performs a binary or: `v = Bor x, y`.
   465  	OpcodeBor
   466  
   467  	// OpcodeBxor performs a binary xor: `v = Bxor x, y`.
   468  	OpcodeBxor
   469  
   470  	// OpcodeBnot performs a binary not: `v = Bnot x`.
   471  	OpcodeBnot
   472  
   473  	// OpcodeRotl rotates the given integer value to the left: `v = Rotl x, y`.
   474  	OpcodeRotl
   475  
   476  	// OpcodeRotr rotates the given integer value to the right: `v = Rotr x, y`.
   477  	OpcodeRotr
   478  
   479  	// OpcodeIshl does logical shift left: `v = Ishl x, y`.
   480  	OpcodeIshl
   481  
   482  	// OpcodeUshr does logical shift right: `v = Ushr x, y`.
   483  	OpcodeUshr
   484  
   485  	// OpcodeSshr does arithmetic shift right: `v = Sshr x, y`.
   486  	OpcodeSshr
   487  
   488  	// OpcodeClz counts the number of leading zeros: `v = clz x`.
   489  	OpcodeClz
   490  
   491  	// OpcodeCtz counts the number of trailing zeros: `v = ctz x`.
   492  	OpcodeCtz
   493  
   494  	// OpcodePopcnt counts the number of 1-bits: `v = popcnt x`.
   495  	OpcodePopcnt
   496  
   497  	// OpcodeFcmp compares two floating point values: `v = fcmp Cond, x, y`.
   498  	OpcodeFcmp
   499  
   500  	// OpcodeFadd performs a floating point addition: / `v = Fadd x, y`.
   501  	OpcodeFadd
   502  
   503  	// OpcodeFsub performs a floating point subtraction: `v = Fsub x, y`.
   504  	OpcodeFsub
   505  
   506  	// OpcodeFmul performs a floating point multiplication: `v = Fmul x, y`.
   507  	OpcodeFmul
   508  
   509  	// OpcodeSqmulRoundSat performs a lane-wise saturating rounding multiplication
   510  	// in Q15 format: `v = SqmulRoundSat.lane x,y` on vector.
   511  	OpcodeSqmulRoundSat
   512  
   513  	// OpcodeFdiv performs a floating point division: `v = Fdiv x, y`.
   514  	OpcodeFdiv
   515  
   516  	// OpcodeSqrt takes the square root of the given floating point value: `v = sqrt x`.
   517  	OpcodeSqrt
   518  
   519  	// OpcodeFneg negates the given floating point value: `v = Fneg x`.
   520  	OpcodeFneg
   521  
   522  	// OpcodeFabs takes the absolute value of the given floating point value: `v = fabs x`.
   523  	OpcodeFabs
   524  
   525  	// OpcodeFcopysign copies the sign of the second floating point value to the first floating point value:
   526  	// `v = Fcopysign x, y`.
   527  	OpcodeFcopysign
   528  
   529  	// OpcodeFmin takes the minimum of two floating point values: `v = fmin x, y`.
   530  	OpcodeFmin
   531  
   532  	// OpcodeFmax takes the maximum of two floating point values: `v = fmax x, y`.
   533  	OpcodeFmax
   534  
   535  	// OpcodeCeil takes the ceiling of the given floating point value: `v = ceil x`.
   536  	OpcodeCeil
   537  
   538  	// OpcodeFloor takes the floor of the given floating point value: `v = floor x`.
   539  	OpcodeFloor
   540  
   541  	// OpcodeTrunc takes the truncation of the given floating point value: `v = trunc x`.
   542  	OpcodeTrunc
   543  
   544  	// OpcodeNearest takes the nearest integer of the given floating point value: `v = nearest x`.
   545  	OpcodeNearest
   546  
   547  	// OpcodeBitcast is a bitcast operation: `v = bitcast x`.
   548  	OpcodeBitcast
   549  
   550  	// OpcodeBmask ...
   551  	// `v = bmask x`.
   552  	OpcodeBmask
   553  
   554  	// OpcodeIreduce ...
   555  	// `v = ireduce x`.
   556  	OpcodeIreduce
   557  
   558  	// OpcodeSnarrow converts two input vectors x, y into a smaller lane vector by narrowing each lane, signed `v = Snarrow.lane x, y`.
   559  	OpcodeSnarrow
   560  
   561  	// OpcodeUnarrow converts two input vectors x, y into a smaller lane vector by narrowing each lane, unsigned `v = Unarrow.lane x, y`.
   562  	OpcodeUnarrow
   563  
   564  	// OpcodeSwidenLow converts low half of the smaller lane vector to a larger lane vector, sign extended: `v = SwidenLow.lane x`.
   565  	OpcodeSwidenLow
   566  
   567  	// OpcodeSwidenHigh converts high half of the smaller lane vector to a larger lane vector, sign extended: `v = SwidenHigh.lane x`.
   568  	OpcodeSwidenHigh
   569  
   570  	// OpcodeUwidenLow converts low half of the smaller lane vector to a larger lane vector, zero (unsigned) extended: `v = UwidenLow.lane x`.
   571  	OpcodeUwidenLow
   572  
   573  	// OpcodeUwidenHigh converts high half of the smaller lane vector to a larger lane vector, zero (unsigned) extended: `v = UwidenHigh.lane x`.
   574  	OpcodeUwidenHigh
   575  
   576  	// OpcodeIaddPairwise is a lane-wise integer extended pairwise addition producing extended results (twice wider results than the inputs): `v = iadd_pairwise x, y` on vector.
   577  	OpcodeIaddPairwise
   578  
   579  	// OpcodeWideningPairwiseDotProductS ...
   580  	// `v = widening_pairwise_dot_product_s x, y`.
   581  	OpcodeWideningPairwiseDotProductS
   582  
   583  	// OpcodeUExtend zero-extends the given integer: `v = UExtend x, from->to`.
   584  	OpcodeUExtend
   585  
   586  	// OpcodeSExtend sign-extends the given integer: `v = SExtend x, from->to`.
   587  	OpcodeSExtend
   588  
   589  	// OpcodeFpromote promotes the given floating point value: `v = Fpromote x`.
   590  	OpcodeFpromote
   591  
   592  	// OpcodeFvpromoteLow converts the two lower single-precision floating point lanes
   593  	// to the two double-precision lanes of the result: `v = FvpromoteLow.lane x` on vector.
   594  	OpcodeFvpromoteLow
   595  
   596  	// OpcodeFdemote demotes the given float point value: `v = Fdemote x`.
   597  	OpcodeFdemote
   598  
   599  	// OpcodeFvdemote converts the two double-precision floating point lanes
   600  	// to two lower single-precision lanes of the result `v = Fvdemote.lane x`.
   601  	OpcodeFvdemote
   602  
   603  	// OpcodeFcvtToUint ...
   604  	// `v = fcvt_to_uint x`.
   605  	OpcodeFcvtToUint
   606  
   607  	// OpcodeFcvtToSint converts a floating point value to a signed integer: `v = FcvtToSint x`.
   608  	OpcodeFcvtToSint
   609  
   610  	// OpcodeFcvtToUintSat converts a floating point value to an unsigned integer: `v = FcvtToUintSat x`.
   611  	OpcodeFcvtToUintSat
   612  
   613  	// OpcodeFcvtToSintSat ...
   614  	// `v = fcvt_to_sint_sat x`.
   615  	OpcodeFcvtToSintSat
   616  
   617  	// OpcodeFcvtFromUint converts an unsigned integer to a floating point value: `v = FcvtFromUint x`.
   618  	OpcodeFcvtFromUint
   619  
   620  	// OpcodeFcvtFromSint converts a signed integer to a floating point value: `v = FcvtFromSint x`.
   621  	OpcodeFcvtFromSint
   622  
   623  	// OpcodeIsplit ...
   624  	// `lo, hi = isplit x`.
   625  	OpcodeIsplit
   626  
   627  	// OpcodeIconcat ...
   628  	// `v = iconcat lo, hi`.
   629  	OpcodeIconcat
   630  
   631  	// OpcodeAtomicRmw ...
   632  	// `v = atomic_rmw MemFlags, AtomicRmwOp, p, x`.
   633  	OpcodeAtomicRmw
   634  
   635  	// OpcodeAtomicCas ...
   636  	// `v = atomic_cas MemFlags, p, e, x`.
   637  	OpcodeAtomicCas
   638  
   639  	// OpcodeAtomicLoad ...
   640  	// `v = atomic_load MemFlags, p`.
   641  	OpcodeAtomicLoad
   642  
   643  	// OpcodeAtomicStore ...
   644  	// `atomic_store MemFlags, x, p`.
   645  	OpcodeAtomicStore
   646  
   647  	// OpcodeFence ...
   648  	// `fence`.
   649  	OpcodeFence
   650  
   651  	// opcodeEnd marks the end of the opcode list.
   652  	opcodeEnd
   653  )
   654  
   655  // returnTypesFn provides the info to determine the type of instruction.
   656  // t1 is the type of the first result, ts are the types of the remaining results.
   657  type returnTypesFn func(b *builder, instr *Instruction) (t1 Type, ts []Type)
   658  
   659  var (
   660  	returnTypesFnNoReturns returnTypesFn = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return typeInvalid, nil }
   661  	returnTypesFnSingle                  = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return instr.typ, nil }
   662  	returnTypesFnI32                     = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return TypeI32, nil }
   663  	returnTypesFnF32                     = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return TypeF32, nil }
   664  	returnTypesFnF64                     = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return TypeF64, nil }
   665  	returnTypesFnV128                    = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return TypeV128, nil }
   666  )
   667  
   668  // sideEffect provides the info to determine if an instruction has side effects which
   669  // is used to determine if it can be optimized out, interchanged with others, etc.
   670  type sideEffect byte
   671  
   672  const (
   673  	sideEffectUnknown sideEffect = iota
   674  	// sideEffectStrict represents an instruction with side effects, and should be always alive plus cannot be reordered.
   675  	sideEffectStrict
   676  	// sideEffectTraps represents an instruction that can trap, and should be always alive but can be reordered within the group.
   677  	sideEffectTraps
   678  	// sideEffectNone represents an instruction without side effects, and can be eliminated if the result is not used, plus can be reordered within the group.
   679  	sideEffectNone
   680  )
   681  
   682  // instructionSideEffects provides the info to determine if an instruction has side effects.
   683  // Instructions with side effects must not be eliminated regardless whether the result is used or not.
   684  var instructionSideEffects = [opcodeEnd]sideEffect{
   685  	OpcodeUndefined:          sideEffectStrict,
   686  	OpcodeJump:               sideEffectStrict,
   687  	OpcodeIconst:             sideEffectNone,
   688  	OpcodeCall:               sideEffectStrict,
   689  	OpcodeCallIndirect:       sideEffectStrict,
   690  	OpcodeIadd:               sideEffectNone,
   691  	OpcodeImul:               sideEffectNone,
   692  	OpcodeIsub:               sideEffectNone,
   693  	OpcodeIcmp:               sideEffectNone,
   694  	OpcodeExtractlane:        sideEffectNone,
   695  	OpcodeInsertlane:         sideEffectNone,
   696  	OpcodeBand:               sideEffectNone,
   697  	OpcodeBor:                sideEffectNone,
   698  	OpcodeBxor:               sideEffectNone,
   699  	OpcodeRotl:               sideEffectNone,
   700  	OpcodeRotr:               sideEffectNone,
   701  	OpcodeFcmp:               sideEffectNone,
   702  	OpcodeFadd:               sideEffectNone,
   703  	OpcodeClz:                sideEffectNone,
   704  	OpcodeCtz:                sideEffectNone,
   705  	OpcodePopcnt:             sideEffectNone,
   706  	OpcodeLoad:               sideEffectNone,
   707  	OpcodeLoadSplat:          sideEffectNone,
   708  	OpcodeUload8:             sideEffectNone,
   709  	OpcodeUload16:            sideEffectNone,
   710  	OpcodeUload32:            sideEffectNone,
   711  	OpcodeSload8:             sideEffectNone,
   712  	OpcodeSload16:            sideEffectNone,
   713  	OpcodeSload32:            sideEffectNone,
   714  	OpcodeSExtend:            sideEffectNone,
   715  	OpcodeUExtend:            sideEffectNone,
   716  	OpcodeSwidenLow:          sideEffectNone,
   717  	OpcodeUwidenLow:          sideEffectNone,
   718  	OpcodeSwidenHigh:         sideEffectNone,
   719  	OpcodeUwidenHigh:         sideEffectNone,
   720  	OpcodeSnarrow:            sideEffectNone,
   721  	OpcodeUnarrow:            sideEffectNone,
   722  	OpcodeSwizzle:            sideEffectNone,
   723  	OpcodeShuffle:            sideEffectNone,
   724  	OpcodeSplat:              sideEffectNone,
   725  	OpcodeFsub:               sideEffectNone,
   726  	OpcodeF32const:           sideEffectNone,
   727  	OpcodeF64const:           sideEffectNone,
   728  	OpcodeIshl:               sideEffectNone,
   729  	OpcodeSshr:               sideEffectNone,
   730  	OpcodeUshr:               sideEffectNone,
   731  	OpcodeStore:              sideEffectStrict,
   732  	OpcodeIstore8:            sideEffectStrict,
   733  	OpcodeIstore16:           sideEffectStrict,
   734  	OpcodeIstore32:           sideEffectStrict,
   735  	OpcodeExitWithCode:       sideEffectStrict,
   736  	OpcodeExitIfTrueWithCode: sideEffectStrict,
   737  	OpcodeReturn:             sideEffectStrict,
   738  	OpcodeBrz:                sideEffectStrict,
   739  	OpcodeBrnz:               sideEffectStrict,
   740  	OpcodeBrTable:            sideEffectStrict,
   741  	OpcodeFdiv:               sideEffectNone,
   742  	OpcodeFmul:               sideEffectNone,
   743  	OpcodeFmax:               sideEffectNone,
   744  	OpcodeSqmulRoundSat:      sideEffectNone,
   745  	OpcodeSelect:             sideEffectNone,
   746  	OpcodeFmin:               sideEffectNone,
   747  	OpcodeFneg:               sideEffectNone,
   748  	OpcodeFcvtToSint:         sideEffectTraps,
   749  	OpcodeFcvtToUint:         sideEffectTraps,
   750  	OpcodeFcvtFromSint:       sideEffectNone,
   751  	OpcodeFcvtFromUint:       sideEffectNone,
   752  	OpcodeFcvtToSintSat:      sideEffectNone,
   753  	OpcodeFcvtToUintSat:      sideEffectNone,
   754  	OpcodeVFcvtFromUint:      sideEffectNone,
   755  	OpcodeVFcvtFromSint:      sideEffectNone,
   756  	OpcodeFdemote:            sideEffectNone,
   757  	OpcodeFvpromoteLow:       sideEffectNone,
   758  	OpcodeFvdemote:           sideEffectNone,
   759  	OpcodeFpromote:           sideEffectNone,
   760  	OpcodeBitcast:            sideEffectNone,
   761  	OpcodeIreduce:            sideEffectNone,
   762  	OpcodeSqrt:               sideEffectNone,
   763  	OpcodeCeil:               sideEffectNone,
   764  	OpcodeFloor:              sideEffectNone,
   765  	OpcodeTrunc:              sideEffectNone,
   766  	OpcodeNearest:            sideEffectNone,
   767  	OpcodeSdiv:               sideEffectTraps,
   768  	OpcodeSrem:               sideEffectTraps,
   769  	OpcodeUdiv:               sideEffectTraps,
   770  	OpcodeUrem:               sideEffectTraps,
   771  	OpcodeFabs:               sideEffectNone,
   772  	OpcodeFcopysign:          sideEffectNone,
   773  	OpcodeIaddPairwise:       sideEffectNone,
   774  	OpcodeVconst:             sideEffectNone,
   775  	OpcodeVbor:               sideEffectNone,
   776  	OpcodeVbxor:              sideEffectNone,
   777  	OpcodeVband:              sideEffectNone,
   778  	OpcodeVbandnot:           sideEffectNone,
   779  	OpcodeVbnot:              sideEffectNone,
   780  	OpcodeVbitselect:         sideEffectNone,
   781  	OpcodeVanyTrue:           sideEffectNone,
   782  	OpcodeVallTrue:           sideEffectNone,
   783  	OpcodeVhighBits:          sideEffectNone,
   784  	OpcodeVIadd:              sideEffectNone,
   785  	OpcodeVSaddSat:           sideEffectNone,
   786  	OpcodeVUaddSat:           sideEffectNone,
   787  	OpcodeVIsub:              sideEffectNone,
   788  	OpcodeVSsubSat:           sideEffectNone,
   789  	OpcodeVUsubSat:           sideEffectNone,
   790  	OpcodeVIcmp:              sideEffectNone,
   791  	OpcodeVImin:              sideEffectNone,
   792  	OpcodeVUmin:              sideEffectNone,
   793  	OpcodeVImax:              sideEffectNone,
   794  	OpcodeVUmax:              sideEffectNone,
   795  	OpcodeVAvgRound:          sideEffectNone,
   796  	OpcodeVImul:              sideEffectNone,
   797  	OpcodeVIabs:              sideEffectNone,
   798  	OpcodeVIneg:              sideEffectNone,
   799  	OpcodeVIpopcnt:           sideEffectNone,
   800  	OpcodeVIshl:              sideEffectNone,
   801  	OpcodeVSshr:              sideEffectNone,
   802  	OpcodeVUshr:              sideEffectNone,
   803  	OpcodeVSqrt:              sideEffectNone,
   804  	OpcodeVFabs:              sideEffectNone,
   805  	OpcodeVFmin:              sideEffectNone,
   806  	OpcodeVFmax:              sideEffectNone,
   807  	OpcodeVFneg:              sideEffectNone,
   808  	OpcodeVFadd:              sideEffectNone,
   809  	OpcodeVFsub:              sideEffectNone,
   810  	OpcodeVFmul:              sideEffectNone,
   811  	OpcodeVFdiv:              sideEffectNone,
   812  	OpcodeVFcmp:              sideEffectNone,
   813  	OpcodeVCeil:              sideEffectNone,
   814  	OpcodeVFloor:             sideEffectNone,
   815  	OpcodeVTrunc:             sideEffectNone,
   816  	OpcodeVNearest:           sideEffectNone,
   817  	OpcodeVMaxPseudo:         sideEffectNone,
   818  	OpcodeVMinPseudo:         sideEffectNone,
   819  	OpcodeVFcvtToUintSat:     sideEffectNone,
   820  	OpcodeVFcvtToSintSat:     sideEffectNone,
   821  	OpcodeVZeroExtLoad:       sideEffectNone,
   822  }
   823  
   824  // sideEffect returns true if this instruction has side effects.
   825  func (i *Instruction) sideEffect() sideEffect {
   826  	if e := instructionSideEffects[i.opcode]; e == sideEffectUnknown {
   827  		panic("BUG: side effect info not registered for " + i.opcode.String())
   828  	} else {
   829  		return e
   830  	}
   831  }
   832  
   833  // instructionReturnTypes provides the function to determine the return types of an instruction.
   834  var instructionReturnTypes = [opcodeEnd]returnTypesFn{
   835  	OpcodeIaddPairwise: returnTypesFnV128,
   836  	OpcodeVbor:         returnTypesFnV128,
   837  	OpcodeVbxor:        returnTypesFnV128,
   838  	OpcodeVband:        returnTypesFnV128,
   839  	OpcodeVbnot:        returnTypesFnV128,
   840  	OpcodeVbandnot:     returnTypesFnV128,
   841  	OpcodeVbitselect:   returnTypesFnV128,
   842  	OpcodeVanyTrue:     returnTypesFnI32,
   843  	OpcodeVallTrue:     returnTypesFnI32,
   844  	OpcodeVhighBits:    returnTypesFnI32,
   845  	OpcodeVIadd:        returnTypesFnV128,
   846  	OpcodeVSaddSat:     returnTypesFnV128,
   847  	OpcodeVUaddSat:     returnTypesFnV128,
   848  	OpcodeVIsub:        returnTypesFnV128,
   849  	OpcodeVSsubSat:     returnTypesFnV128,
   850  	OpcodeVUsubSat:     returnTypesFnV128,
   851  	OpcodeVIcmp:        returnTypesFnV128,
   852  	OpcodeVImin:        returnTypesFnV128,
   853  	OpcodeVUmin:        returnTypesFnV128,
   854  	OpcodeVImax:        returnTypesFnV128,
   855  	OpcodeVUmax:        returnTypesFnV128,
   856  	OpcodeVImul:        returnTypesFnV128,
   857  	OpcodeVAvgRound:    returnTypesFnV128,
   858  	OpcodeVIabs:        returnTypesFnV128,
   859  	OpcodeVIneg:        returnTypesFnV128,
   860  	OpcodeVIpopcnt:     returnTypesFnV128,
   861  	OpcodeVIshl:        returnTypesFnV128,
   862  	OpcodeVSshr:        returnTypesFnV128,
   863  	OpcodeVUshr:        returnTypesFnV128,
   864  	OpcodeExtractlane:  returnTypesFnSingle,
   865  	OpcodeInsertlane:   returnTypesFnV128,
   866  	OpcodeBand:         returnTypesFnSingle,
   867  	OpcodeFcopysign:    returnTypesFnSingle,
   868  	OpcodeBitcast:      returnTypesFnSingle,
   869  	OpcodeBor:          returnTypesFnSingle,
   870  	OpcodeBxor:         returnTypesFnSingle,
   871  	OpcodeRotl:         returnTypesFnSingle,
   872  	OpcodeRotr:         returnTypesFnSingle,
   873  	OpcodeIshl:         returnTypesFnSingle,
   874  	OpcodeSshr:         returnTypesFnSingle,
   875  	OpcodeSdiv:         returnTypesFnSingle,
   876  	OpcodeSrem:         returnTypesFnSingle,
   877  	OpcodeUdiv:         returnTypesFnSingle,
   878  	OpcodeUrem:         returnTypesFnSingle,
   879  	OpcodeUshr:         returnTypesFnSingle,
   880  	OpcodeJump:         returnTypesFnNoReturns,
   881  	OpcodeUndefined:    returnTypesFnNoReturns,
   882  	OpcodeIconst:       returnTypesFnSingle,
   883  	OpcodeSelect:       returnTypesFnSingle,
   884  	OpcodeSExtend:      returnTypesFnSingle,
   885  	OpcodeUExtend:      returnTypesFnSingle,
   886  	OpcodeSwidenLow:    returnTypesFnV128,
   887  	OpcodeUwidenLow:    returnTypesFnV128,
   888  	OpcodeSwidenHigh:   returnTypesFnV128,
   889  	OpcodeUwidenHigh:   returnTypesFnV128,
   890  	OpcodeSnarrow:      returnTypesFnV128,
   891  	OpcodeUnarrow:      returnTypesFnV128,
   892  	OpcodeSwizzle:      returnTypesFnSingle,
   893  	OpcodeShuffle:      returnTypesFnV128,
   894  	OpcodeSplat:        returnTypesFnV128,
   895  	OpcodeIreduce:      returnTypesFnSingle,
   896  	OpcodeFabs:         returnTypesFnSingle,
   897  	OpcodeSqrt:         returnTypesFnSingle,
   898  	OpcodeCeil:         returnTypesFnSingle,
   899  	OpcodeFloor:        returnTypesFnSingle,
   900  	OpcodeTrunc:        returnTypesFnSingle,
   901  	OpcodeNearest:      returnTypesFnSingle,
   902  	OpcodeCallIndirect: func(b *builder, instr *Instruction) (t1 Type, ts []Type) {
   903  		sigID := SignatureID(instr.u1)
   904  		sig, ok := b.signatures[sigID]
   905  		if !ok {
   906  			panic("BUG")
   907  		}
   908  		switch len(sig.Results) {
   909  		case 0:
   910  			t1 = typeInvalid
   911  		case 1:
   912  			t1 = sig.Results[0]
   913  		default:
   914  			t1, ts = sig.Results[0], sig.Results[1:]
   915  		}
   916  		return
   917  	},
   918  	OpcodeCall: func(b *builder, instr *Instruction) (t1 Type, ts []Type) {
   919  		sigID := SignatureID(instr.u2)
   920  		sig, ok := b.signatures[sigID]
   921  		if !ok {
   922  			panic("BUG")
   923  		}
   924  		switch len(sig.Results) {
   925  		case 0:
   926  			t1 = typeInvalid
   927  		case 1:
   928  			t1 = sig.Results[0]
   929  		default:
   930  			t1, ts = sig.Results[0], sig.Results[1:]
   931  		}
   932  		return
   933  	},
   934  	OpcodeLoad:               returnTypesFnSingle,
   935  	OpcodeVZeroExtLoad:       returnTypesFnV128,
   936  	OpcodeLoadSplat:          returnTypesFnV128,
   937  	OpcodeIadd:               returnTypesFnSingle,
   938  	OpcodeIsub:               returnTypesFnSingle,
   939  	OpcodeImul:               returnTypesFnSingle,
   940  	OpcodeIcmp:               returnTypesFnI32,
   941  	OpcodeFcmp:               returnTypesFnI32,
   942  	OpcodeFadd:               returnTypesFnSingle,
   943  	OpcodeFsub:               returnTypesFnSingle,
   944  	OpcodeFdiv:               returnTypesFnSingle,
   945  	OpcodeFmul:               returnTypesFnSingle,
   946  	OpcodeFmax:               returnTypesFnSingle,
   947  	OpcodeFmin:               returnTypesFnSingle,
   948  	OpcodeSqmulRoundSat:      returnTypesFnV128,
   949  	OpcodeF32const:           returnTypesFnF32,
   950  	OpcodeF64const:           returnTypesFnF64,
   951  	OpcodeClz:                returnTypesFnSingle,
   952  	OpcodeCtz:                returnTypesFnSingle,
   953  	OpcodePopcnt:             returnTypesFnSingle,
   954  	OpcodeStore:              returnTypesFnNoReturns,
   955  	OpcodeIstore8:            returnTypesFnNoReturns,
   956  	OpcodeIstore16:           returnTypesFnNoReturns,
   957  	OpcodeIstore32:           returnTypesFnNoReturns,
   958  	OpcodeExitWithCode:       returnTypesFnNoReturns,
   959  	OpcodeExitIfTrueWithCode: returnTypesFnNoReturns,
   960  	OpcodeReturn:             returnTypesFnNoReturns,
   961  	OpcodeBrz:                returnTypesFnNoReturns,
   962  	OpcodeBrnz:               returnTypesFnNoReturns,
   963  	OpcodeBrTable:            returnTypesFnNoReturns,
   964  	OpcodeUload8:             returnTypesFnSingle,
   965  	OpcodeUload16:            returnTypesFnSingle,
   966  	OpcodeUload32:            returnTypesFnSingle,
   967  	OpcodeSload8:             returnTypesFnSingle,
   968  	OpcodeSload16:            returnTypesFnSingle,
   969  	OpcodeSload32:            returnTypesFnSingle,
   970  	OpcodeFcvtToSint:         returnTypesFnSingle,
   971  	OpcodeFcvtToUint:         returnTypesFnSingle,
   972  	OpcodeFcvtFromSint:       returnTypesFnSingle,
   973  	OpcodeFcvtFromUint:       returnTypesFnSingle,
   974  	OpcodeFcvtToSintSat:      returnTypesFnSingle,
   975  	OpcodeFcvtToUintSat:      returnTypesFnSingle,
   976  	OpcodeVFcvtFromUint:      returnTypesFnV128,
   977  	OpcodeVFcvtFromSint:      returnTypesFnV128,
   978  	OpcodeFneg:               returnTypesFnSingle,
   979  	OpcodeFdemote:            returnTypesFnF32,
   980  	OpcodeFvdemote:           returnTypesFnV128,
   981  	OpcodeFvpromoteLow:       returnTypesFnV128,
   982  	OpcodeFpromote:           returnTypesFnF64,
   983  	OpcodeVconst:             returnTypesFnV128,
   984  	OpcodeVFabs:              returnTypesFnV128,
   985  	OpcodeVSqrt:              returnTypesFnV128,
   986  	OpcodeVFmax:              returnTypesFnV128,
   987  	OpcodeVFmin:              returnTypesFnV128,
   988  	OpcodeVFneg:              returnTypesFnV128,
   989  	OpcodeVFadd:              returnTypesFnV128,
   990  	OpcodeVFsub:              returnTypesFnV128,
   991  	OpcodeVFmul:              returnTypesFnV128,
   992  	OpcodeVFdiv:              returnTypesFnV128,
   993  	OpcodeVFcmp:              returnTypesFnV128,
   994  	OpcodeVCeil:              returnTypesFnV128,
   995  	OpcodeVFloor:             returnTypesFnV128,
   996  	OpcodeVTrunc:             returnTypesFnV128,
   997  	OpcodeVNearest:           returnTypesFnV128,
   998  	OpcodeVMaxPseudo:         returnTypesFnV128,
   999  	OpcodeVMinPseudo:         returnTypesFnV128,
  1000  	OpcodeVFcvtToUintSat:     returnTypesFnV128,
  1001  	OpcodeVFcvtToSintSat:     returnTypesFnV128,
  1002  }
  1003  
  1004  // AsLoad initializes this instruction as a store instruction with OpcodeLoad.
  1005  func (i *Instruction) AsLoad(ptr Value, offset uint32, typ Type) *Instruction {
  1006  	i.opcode = OpcodeLoad
  1007  	i.v = ptr
  1008  	i.u1 = uint64(offset)
  1009  	i.typ = typ
  1010  	return i
  1011  }
  1012  
  1013  // AsExtLoad initializes this instruction as a store instruction with OpcodeLoad.
  1014  func (i *Instruction) AsExtLoad(op Opcode, ptr Value, offset uint32, dst64bit bool) *Instruction {
  1015  	i.opcode = op
  1016  	i.v = ptr
  1017  	i.u1 = uint64(offset)
  1018  	if dst64bit {
  1019  		i.typ = TypeI64
  1020  	} else {
  1021  		i.typ = TypeI32
  1022  	}
  1023  	return i
  1024  }
  1025  
  1026  // AsVZeroExtLoad initializes this instruction as a store instruction with OpcodeVExtLoad.
  1027  func (i *Instruction) AsVZeroExtLoad(ptr Value, offset uint32, scalarType Type) *Instruction {
  1028  	i.opcode = OpcodeVZeroExtLoad
  1029  	i.v = ptr
  1030  	i.u1 = uint64(offset)
  1031  	i.u2 = uint64(scalarType)
  1032  	i.typ = TypeV128
  1033  	return i
  1034  }
  1035  
  1036  // VZeroExtLoadData returns the operands for a load instruction. The returned `typ` is the scalar type of the load target.
  1037  func (i *Instruction) VZeroExtLoadData() (ptr Value, offset uint32, typ Type) {
  1038  	return i.v, uint32(i.u1), Type(i.u2)
  1039  }
  1040  
  1041  // AsLoadSplat initializes this instruction as a store instruction with OpcodeLoadSplat.
  1042  func (i *Instruction) AsLoadSplat(ptr Value, offset uint32, lane VecLane) *Instruction {
  1043  	i.opcode = OpcodeLoadSplat
  1044  	i.v = ptr
  1045  	i.u1 = uint64(offset)
  1046  	i.u2 = uint64(lane)
  1047  	i.typ = TypeV128
  1048  	return i
  1049  }
  1050  
  1051  // LoadData returns the operands for a load instruction.
  1052  func (i *Instruction) LoadData() (ptr Value, offset uint32, typ Type) {
  1053  	return i.v, uint32(i.u1), i.typ
  1054  }
  1055  
  1056  // LoadSplatData returns the operands for a load splat instruction.
  1057  func (i *Instruction) LoadSplatData() (ptr Value, offset uint32, lane VecLane) {
  1058  	return i.v, uint32(i.u1), VecLane(i.u2)
  1059  }
  1060  
  1061  // AsStore initializes this instruction as a store instruction with OpcodeStore.
  1062  func (i *Instruction) AsStore(storeOp Opcode, value, ptr Value, offset uint32) *Instruction {
  1063  	i.opcode = storeOp
  1064  	i.v = value
  1065  	i.v2 = ptr
  1066  
  1067  	var dstSize uint64
  1068  	switch storeOp {
  1069  	case OpcodeStore:
  1070  		dstSize = uint64(value.Type().Bits())
  1071  	case OpcodeIstore8:
  1072  		dstSize = 8
  1073  	case OpcodeIstore16:
  1074  		dstSize = 16
  1075  	case OpcodeIstore32:
  1076  		dstSize = 32
  1077  	default:
  1078  		panic("invalid store opcode" + storeOp.String())
  1079  	}
  1080  	i.u1 = uint64(offset) | dstSize<<32
  1081  	return i
  1082  }
  1083  
  1084  // StoreData returns the operands for a store instruction.
  1085  func (i *Instruction) StoreData() (value, ptr Value, offset uint32, storeSizeInBits byte) {
  1086  	return i.v, i.v2, uint32(i.u1), byte(i.u1 >> 32)
  1087  }
  1088  
  1089  // AsIconst64 initializes this instruction as a 64-bit integer constant instruction with OpcodeIconst.
  1090  func (i *Instruction) AsIconst64(v uint64) *Instruction {
  1091  	i.opcode = OpcodeIconst
  1092  	i.typ = TypeI64
  1093  	i.u1 = v
  1094  	return i
  1095  }
  1096  
  1097  // AsIconst32 initializes this instruction as a 32-bit integer constant instruction with OpcodeIconst.
  1098  func (i *Instruction) AsIconst32(v uint32) *Instruction {
  1099  	i.opcode = OpcodeIconst
  1100  	i.typ = TypeI32
  1101  	i.u1 = uint64(v)
  1102  	return i
  1103  }
  1104  
  1105  // AsIadd initializes this instruction as an integer addition instruction with OpcodeIadd.
  1106  func (i *Instruction) AsIadd(x, y Value) *Instruction {
  1107  	i.opcode = OpcodeIadd
  1108  	i.v = x
  1109  	i.v2 = y
  1110  	i.typ = x.Type()
  1111  	return i
  1112  }
  1113  
  1114  // AsVIadd initializes this instruction as an integer addition instruction with OpcodeVIadd on a vector.
  1115  func (i *Instruction) AsVIadd(x, y Value, lane VecLane) *Instruction {
  1116  	i.opcode = OpcodeVIadd
  1117  	i.v = x
  1118  	i.v2 = y
  1119  	i.u1 = uint64(lane)
  1120  	i.typ = TypeV128
  1121  	return i
  1122  }
  1123  
  1124  // AsIaddPairwise initializes this instruction as a lane-wise integer extended pairwise addition instruction
  1125  // with OpcodeIaddPairwise on a vector.
  1126  func (i *Instruction) AsIaddPairwise(x, y Value, lane VecLane) *Instruction {
  1127  	i.opcode = OpcodeIaddPairwise
  1128  	i.v = x
  1129  	i.v2 = y
  1130  	i.u1 = uint64(lane)
  1131  	i.typ = TypeV128
  1132  	return i
  1133  }
  1134  
  1135  // AsVSaddSat initializes this instruction as a vector addition with saturation instruction with OpcodeVSaddSat on a vector.
  1136  func (i *Instruction) AsVSaddSat(x, y Value, lane VecLane) *Instruction {
  1137  	i.opcode = OpcodeVSaddSat
  1138  	i.v = x
  1139  	i.v2 = y
  1140  	i.u1 = uint64(lane)
  1141  	i.typ = TypeV128
  1142  	return i
  1143  }
  1144  
  1145  // AsVUaddSat initializes this instruction as a vector addition with saturation instruction with OpcodeVUaddSat on a vector.
  1146  func (i *Instruction) AsVUaddSat(x, y Value, lane VecLane) *Instruction {
  1147  	i.opcode = OpcodeVUaddSat
  1148  	i.v = x
  1149  	i.v2 = y
  1150  	i.u1 = uint64(lane)
  1151  	i.typ = TypeV128
  1152  	return i
  1153  }
  1154  
  1155  // AsVIsub initializes this instruction as an integer subtraction instruction with OpcodeVIsub on a vector.
  1156  func (i *Instruction) AsVIsub(x, y Value, lane VecLane) *Instruction {
  1157  	i.opcode = OpcodeVIsub
  1158  	i.v = x
  1159  	i.v2 = y
  1160  	i.u1 = uint64(lane)
  1161  	i.typ = TypeV128
  1162  	return i
  1163  }
  1164  
  1165  // AsVSsubSat initializes this instruction as a vector addition with saturation instruction with OpcodeVSsubSat on a vector.
  1166  func (i *Instruction) AsVSsubSat(x, y Value, lane VecLane) *Instruction {
  1167  	i.opcode = OpcodeVSsubSat
  1168  	i.v = x
  1169  	i.v2 = y
  1170  	i.u1 = uint64(lane)
  1171  	i.typ = TypeV128
  1172  	return i
  1173  }
  1174  
  1175  // AsVUsubSat initializes this instruction as a vector addition with saturation instruction with OpcodeVUsubSat on a vector.
  1176  func (i *Instruction) AsVUsubSat(x, y Value, lane VecLane) *Instruction {
  1177  	i.opcode = OpcodeVUsubSat
  1178  	i.v = x
  1179  	i.v2 = y
  1180  	i.u1 = uint64(lane)
  1181  	i.typ = TypeV128
  1182  	return i
  1183  }
  1184  
  1185  // AsVImin initializes this instruction as a signed integer min instruction with OpcodeVImin on a vector.
  1186  func (i *Instruction) AsVImin(x, y Value, lane VecLane) *Instruction {
  1187  	i.opcode = OpcodeVImin
  1188  	i.v = x
  1189  	i.v2 = y
  1190  	i.u1 = uint64(lane)
  1191  	i.typ = TypeV128
  1192  	return i
  1193  }
  1194  
  1195  // AsVUmin initializes this instruction as an unsigned integer min instruction with OpcodeVUmin on a vector.
  1196  func (i *Instruction) AsVUmin(x, y Value, lane VecLane) *Instruction {
  1197  	i.opcode = OpcodeVUmin
  1198  	i.v = x
  1199  	i.v2 = y
  1200  	i.u1 = uint64(lane)
  1201  	i.typ = TypeV128
  1202  	return i
  1203  }
  1204  
  1205  // AsVImax initializes this instruction as a signed integer max instruction with OpcodeVImax on a vector.
  1206  func (i *Instruction) AsVImax(x, y Value, lane VecLane) *Instruction {
  1207  	i.opcode = OpcodeVImax
  1208  	i.v = x
  1209  	i.v2 = y
  1210  	i.u1 = uint64(lane)
  1211  	i.typ = TypeV128
  1212  	return i
  1213  }
  1214  
  1215  // AsVUmax initializes this instruction as an unsigned integer max instruction with OpcodeVUmax on a vector.
  1216  func (i *Instruction) AsVUmax(x, y Value, lane VecLane) *Instruction {
  1217  	i.opcode = OpcodeVUmax
  1218  	i.v = x
  1219  	i.v2 = y
  1220  	i.u1 = uint64(lane)
  1221  	i.typ = TypeV128
  1222  	return i
  1223  }
  1224  
  1225  // AsVAvgRound initializes this instruction as an unsigned integer avg instruction, truncating to zero with OpcodeVAvgRound on a vector.
  1226  func (i *Instruction) AsVAvgRound(x, y Value, lane VecLane) *Instruction {
  1227  	i.opcode = OpcodeVAvgRound
  1228  	i.v = x
  1229  	i.v2 = y
  1230  	i.u1 = uint64(lane)
  1231  	i.typ = TypeV128
  1232  	return i
  1233  }
  1234  
  1235  // AsVImul initializes this instruction as an integer multiplication with OpcodeVImul on a vector.
  1236  func (i *Instruction) AsVImul(x, y Value, lane VecLane) *Instruction {
  1237  	i.opcode = OpcodeVImul
  1238  	i.v = x
  1239  	i.v2 = y
  1240  	i.u1 = uint64(lane)
  1241  	i.typ = TypeV128
  1242  	return i
  1243  }
  1244  
  1245  // AsSqmulRoundSat initializes this instruction as a lane-wise saturating rounding multiplication
  1246  // in Q15 format with OpcodeSqmulRoundSat on a vector.
  1247  func (i *Instruction) AsSqmulRoundSat(x, y Value, lane VecLane) *Instruction {
  1248  	i.opcode = OpcodeSqmulRoundSat
  1249  	i.v = x
  1250  	i.v2 = y
  1251  	i.u1 = uint64(lane)
  1252  	i.typ = TypeV128
  1253  	return i
  1254  }
  1255  
  1256  // AsVIabs initializes this instruction as a vector absolute value with OpcodeVIabs.
  1257  func (i *Instruction) AsVIabs(x Value, lane VecLane) *Instruction {
  1258  	i.opcode = OpcodeVIabs
  1259  	i.v = x
  1260  	i.u1 = uint64(lane)
  1261  	i.typ = TypeV128
  1262  	return i
  1263  }
  1264  
  1265  // AsVIneg initializes this instruction as a vector negation with OpcodeVIneg.
  1266  func (i *Instruction) AsVIneg(x Value, lane VecLane) *Instruction {
  1267  	i.opcode = OpcodeVIneg
  1268  	i.v = x
  1269  	i.u1 = uint64(lane)
  1270  	i.typ = TypeV128
  1271  	return i
  1272  }
  1273  
  1274  // AsVIpopcnt initializes this instruction as a Population Count instruction with OpcodeVIpopcnt on a vector.
  1275  func (i *Instruction) AsVIpopcnt(x Value, lane VecLane) *Instruction {
  1276  	if lane != VecLaneI8x16 {
  1277  		panic("Unsupported lane type " + lane.String())
  1278  	}
  1279  	i.opcode = OpcodeVIpopcnt
  1280  	i.v = x
  1281  	i.u1 = uint64(lane)
  1282  	i.typ = TypeV128
  1283  	return i
  1284  }
  1285  
  1286  // AsVSqrt initializes this instruction as a sqrt instruction with OpcodeVSqrt on a vector.
  1287  func (i *Instruction) AsVSqrt(x Value, lane VecLane) *Instruction {
  1288  	i.opcode = OpcodeVSqrt
  1289  	i.v = x
  1290  	i.u1 = uint64(lane)
  1291  	i.typ = TypeV128
  1292  	return i
  1293  }
  1294  
  1295  // AsVFabs initializes this instruction as a float abs instruction with OpcodeVFabs on a vector.
  1296  func (i *Instruction) AsVFabs(x Value, lane VecLane) *Instruction {
  1297  	i.opcode = OpcodeVFabs
  1298  	i.v = x
  1299  	i.u1 = uint64(lane)
  1300  	i.typ = TypeV128
  1301  	return i
  1302  }
  1303  
  1304  // AsVFneg initializes this instruction as a float neg instruction with OpcodeVFneg on a vector.
  1305  func (i *Instruction) AsVFneg(x Value, lane VecLane) *Instruction {
  1306  	i.opcode = OpcodeVFneg
  1307  	i.v = x
  1308  	i.u1 = uint64(lane)
  1309  	i.typ = TypeV128
  1310  	return i
  1311  }
  1312  
  1313  // AsVFmax initializes this instruction as a float max instruction with OpcodeVFmax on a vector.
  1314  func (i *Instruction) AsVFmax(x, y Value, lane VecLane) *Instruction {
  1315  	i.opcode = OpcodeVFmax
  1316  	i.v = x
  1317  	i.v2 = y
  1318  	i.u1 = uint64(lane)
  1319  	i.typ = TypeV128
  1320  	return i
  1321  }
  1322  
  1323  // AsVFmin initializes this instruction as a float min instruction with OpcodeVFmin on a vector.
  1324  func (i *Instruction) AsVFmin(x, y Value, lane VecLane) *Instruction {
  1325  	i.opcode = OpcodeVFmin
  1326  	i.v = x
  1327  	i.v2 = y
  1328  	i.u1 = uint64(lane)
  1329  	i.typ = TypeV128
  1330  	return i
  1331  }
  1332  
  1333  // AsVFadd initializes this instruction as a floating point add instruction with OpcodeVFadd on a vector.
  1334  func (i *Instruction) AsVFadd(x, y Value, lane VecLane) *Instruction {
  1335  	i.opcode = OpcodeVFadd
  1336  	i.v = x
  1337  	i.v2 = y
  1338  	i.u1 = uint64(lane)
  1339  	i.typ = TypeV128
  1340  	return i
  1341  }
  1342  
  1343  // AsVFsub initializes this instruction as a floating point subtraction instruction with OpcodeVFsub on a vector.
  1344  func (i *Instruction) AsVFsub(x, y Value, lane VecLane) *Instruction {
  1345  	i.opcode = OpcodeVFsub
  1346  	i.v = x
  1347  	i.v2 = y
  1348  	i.u1 = uint64(lane)
  1349  	i.typ = TypeV128
  1350  	return i
  1351  }
  1352  
  1353  // AsVFmul initializes this instruction as a floating point multiplication instruction with OpcodeVFmul on a vector.
  1354  func (i *Instruction) AsVFmul(x, y Value, lane VecLane) *Instruction {
  1355  	i.opcode = OpcodeVFmul
  1356  	i.v = x
  1357  	i.v2 = y
  1358  	i.u1 = uint64(lane)
  1359  	i.typ = TypeV128
  1360  	return i
  1361  }
  1362  
  1363  // AsVFdiv initializes this instruction as a floating point division instruction with OpcodeVFdiv on a vector.
  1364  func (i *Instruction) AsVFdiv(x, y Value, lane VecLane) *Instruction {
  1365  	i.opcode = OpcodeVFdiv
  1366  	i.v = x
  1367  	i.v2 = y
  1368  	i.u1 = uint64(lane)
  1369  	i.typ = TypeV128
  1370  	return i
  1371  }
  1372  
  1373  // AsImul initializes this instruction as an integer addition instruction with OpcodeImul.
  1374  func (i *Instruction) AsImul(x, y Value) *Instruction {
  1375  	i.opcode = OpcodeImul
  1376  	i.v = x
  1377  	i.v2 = y
  1378  	i.typ = x.Type()
  1379  	return i
  1380  }
  1381  
  1382  func (i *Instruction) Insert(b Builder) *Instruction {
  1383  	b.InsertInstruction(i)
  1384  	return i
  1385  }
  1386  
  1387  // AsIsub initializes this instruction as an integer subtraction instruction with OpcodeIsub.
  1388  func (i *Instruction) AsIsub(x, y Value) *Instruction {
  1389  	i.opcode = OpcodeIsub
  1390  	i.v = x
  1391  	i.v2 = y
  1392  	i.typ = x.Type()
  1393  	return i
  1394  }
  1395  
  1396  // AsIcmp initializes this instruction as an integer comparison instruction with OpcodeIcmp.
  1397  func (i *Instruction) AsIcmp(x, y Value, c IntegerCmpCond) *Instruction {
  1398  	i.opcode = OpcodeIcmp
  1399  	i.v = x
  1400  	i.v2 = y
  1401  	i.u1 = uint64(c)
  1402  	i.typ = TypeI32
  1403  	return i
  1404  }
  1405  
  1406  // AsFcmp initializes this instruction as an integer comparison instruction with OpcodeFcmp.
  1407  func (i *Instruction) AsFcmp(x, y Value, c FloatCmpCond) {
  1408  	i.opcode = OpcodeFcmp
  1409  	i.v = x
  1410  	i.v2 = y
  1411  	i.u1 = uint64(c)
  1412  	i.typ = TypeI32
  1413  }
  1414  
  1415  // AsVIcmp initializes this instruction as an integer vector comparison instruction with OpcodeVIcmp.
  1416  func (i *Instruction) AsVIcmp(x, y Value, c IntegerCmpCond, lane VecLane) *Instruction {
  1417  	i.opcode = OpcodeVIcmp
  1418  	i.v = x
  1419  	i.v2 = y
  1420  	i.u1 = uint64(c)
  1421  	i.u2 = uint64(lane)
  1422  	i.typ = TypeV128
  1423  	return i
  1424  }
  1425  
  1426  // AsVFcmp initializes this instruction as a float comparison instruction with OpcodeVFcmp on Vector.
  1427  func (i *Instruction) AsVFcmp(x, y Value, c FloatCmpCond, lane VecLane) *Instruction {
  1428  	i.opcode = OpcodeVFcmp
  1429  	i.v = x
  1430  	i.v2 = y
  1431  	i.u1 = uint64(c)
  1432  	i.typ = TypeV128
  1433  	i.u2 = uint64(lane)
  1434  	return i
  1435  }
  1436  
  1437  // AsVCeil initializes this instruction as an instruction with OpcodeCeil.
  1438  func (i *Instruction) AsVCeil(x Value, lane VecLane) *Instruction {
  1439  	i.opcode = OpcodeVCeil
  1440  	i.v = x
  1441  	i.typ = x.Type()
  1442  	i.u1 = uint64(lane)
  1443  	return i
  1444  }
  1445  
  1446  // AsVFloor initializes this instruction as an instruction with OpcodeFloor.
  1447  func (i *Instruction) AsVFloor(x Value, lane VecLane) *Instruction {
  1448  	i.opcode = OpcodeVFloor
  1449  	i.v = x
  1450  	i.typ = x.Type()
  1451  	i.u1 = uint64(lane)
  1452  	return i
  1453  }
  1454  
  1455  // AsVTrunc initializes this instruction as an instruction with OpcodeTrunc.
  1456  func (i *Instruction) AsVTrunc(x Value, lane VecLane) *Instruction {
  1457  	i.opcode = OpcodeVTrunc
  1458  	i.v = x
  1459  	i.typ = x.Type()
  1460  	i.u1 = uint64(lane)
  1461  	return i
  1462  }
  1463  
  1464  // AsVNearest initializes this instruction as an instruction with OpcodeNearest.
  1465  func (i *Instruction) AsVNearest(x Value, lane VecLane) *Instruction {
  1466  	i.opcode = OpcodeVNearest
  1467  	i.v = x
  1468  	i.typ = x.Type()
  1469  	i.u1 = uint64(lane)
  1470  	return i
  1471  }
  1472  
  1473  // AsVMaxPseudo initializes this instruction as an instruction with OpcodeVMaxPseudo.
  1474  func (i *Instruction) AsVMaxPseudo(x, y Value, lane VecLane) *Instruction {
  1475  	i.opcode = OpcodeVMaxPseudo
  1476  	i.typ = x.Type()
  1477  	i.v = x
  1478  	i.v2 = y
  1479  	i.u1 = uint64(lane)
  1480  	return i
  1481  }
  1482  
  1483  // AsVMinPseudo initializes this instruction as an instruction with OpcodeVMinPseudo.
  1484  func (i *Instruction) AsVMinPseudo(x, y Value, lane VecLane) *Instruction {
  1485  	i.opcode = OpcodeVMinPseudo
  1486  	i.typ = x.Type()
  1487  	i.v = x
  1488  	i.v2 = y
  1489  	i.u1 = uint64(lane)
  1490  	return i
  1491  }
  1492  
  1493  // AsSDiv initializes this instruction as an integer bitwise and instruction with OpcodeSdiv.
  1494  func (i *Instruction) AsSDiv(x, y, ctx Value) *Instruction {
  1495  	i.opcode = OpcodeSdiv
  1496  	i.v = x
  1497  	i.v2 = y
  1498  	i.v3 = ctx
  1499  	i.typ = x.Type()
  1500  	return i
  1501  }
  1502  
  1503  // AsUDiv initializes this instruction as an integer bitwise and instruction with OpcodeUdiv.
  1504  func (i *Instruction) AsUDiv(x, y, ctx Value) *Instruction {
  1505  	i.opcode = OpcodeUdiv
  1506  	i.v = x
  1507  	i.v2 = y
  1508  	i.v3 = ctx
  1509  	i.typ = x.Type()
  1510  	return i
  1511  }
  1512  
  1513  // AsSRem initializes this instruction as an integer bitwise and instruction with OpcodeSrem.
  1514  func (i *Instruction) AsSRem(x, y, ctx Value) *Instruction {
  1515  	i.opcode = OpcodeSrem
  1516  	i.v = x
  1517  	i.v2 = y
  1518  	i.v3 = ctx
  1519  	i.typ = x.Type()
  1520  	return i
  1521  }
  1522  
  1523  // AsURem initializes this instruction as an integer bitwise and instruction with OpcodeUrem.
  1524  func (i *Instruction) AsURem(x, y, ctx Value) *Instruction {
  1525  	i.opcode = OpcodeUrem
  1526  	i.v = x
  1527  	i.v2 = y
  1528  	i.v3 = ctx
  1529  	i.typ = x.Type()
  1530  	return i
  1531  }
  1532  
  1533  // AsBand initializes this instruction as an integer bitwise and instruction with OpcodeBand.
  1534  func (i *Instruction) AsBand(x, amount Value) {
  1535  	i.opcode = OpcodeBand
  1536  	i.v = x
  1537  	i.v2 = amount
  1538  	i.typ = x.Type()
  1539  }
  1540  
  1541  // AsBor initializes this instruction as an integer bitwise or instruction with OpcodeBor.
  1542  func (i *Instruction) AsBor(x, amount Value) {
  1543  	i.opcode = OpcodeBor
  1544  	i.v = x
  1545  	i.v2 = amount
  1546  	i.typ = x.Type()
  1547  }
  1548  
  1549  // AsBxor initializes this instruction as an integer bitwise xor instruction with OpcodeBxor.
  1550  func (i *Instruction) AsBxor(x, amount Value) {
  1551  	i.opcode = OpcodeBxor
  1552  	i.v = x
  1553  	i.v2 = amount
  1554  	i.typ = x.Type()
  1555  }
  1556  
  1557  // AsIshl initializes this instruction as an integer shift left instruction with OpcodeIshl.
  1558  func (i *Instruction) AsIshl(x, amount Value) *Instruction {
  1559  	i.opcode = OpcodeIshl
  1560  	i.v = x
  1561  	i.v2 = amount
  1562  	i.typ = x.Type()
  1563  	return i
  1564  }
  1565  
  1566  // AsVIshl initializes this instruction as an integer shift left instruction with OpcodeVIshl on vector.
  1567  func (i *Instruction) AsVIshl(x, amount Value, lane VecLane) *Instruction {
  1568  	i.opcode = OpcodeVIshl
  1569  	i.v = x
  1570  	i.v2 = amount
  1571  	i.u1 = uint64(lane)
  1572  	i.typ = x.Type()
  1573  	return i
  1574  }
  1575  
  1576  // AsUshr initializes this instruction as an integer unsigned shift right (logical shift right) instruction with OpcodeUshr.
  1577  func (i *Instruction) AsUshr(x, amount Value) *Instruction {
  1578  	i.opcode = OpcodeUshr
  1579  	i.v = x
  1580  	i.v2 = amount
  1581  	i.typ = x.Type()
  1582  	return i
  1583  }
  1584  
  1585  // AsVUshr initializes this instruction as an integer unsigned shift right (logical shift right) instruction with OpcodeVUshr on vector.
  1586  func (i *Instruction) AsVUshr(x, amount Value, lane VecLane) *Instruction {
  1587  	i.opcode = OpcodeVUshr
  1588  	i.v = x
  1589  	i.v2 = amount
  1590  	i.u1 = uint64(lane)
  1591  	i.typ = x.Type()
  1592  	return i
  1593  }
  1594  
  1595  // AsSshr initializes this instruction as an integer signed shift right (arithmetic shift right) instruction with OpcodeSshr.
  1596  func (i *Instruction) AsSshr(x, amount Value) *Instruction {
  1597  	i.opcode = OpcodeSshr
  1598  	i.v = x
  1599  	i.v2 = amount
  1600  	i.typ = x.Type()
  1601  	return i
  1602  }
  1603  
  1604  // AsVSshr initializes this instruction as an integer signed shift right (arithmetic shift right) instruction with OpcodeVSshr on vector.
  1605  func (i *Instruction) AsVSshr(x, amount Value, lane VecLane) *Instruction {
  1606  	i.opcode = OpcodeVSshr
  1607  	i.v = x
  1608  	i.v2 = amount
  1609  	i.u1 = uint64(lane)
  1610  	i.typ = x.Type()
  1611  	return i
  1612  }
  1613  
  1614  // AsExtractlane initializes this instruction as an extract lane instruction with OpcodeExtractlane on vector.
  1615  func (i *Instruction) AsExtractlane(x Value, index byte, lane VecLane, signed bool) *Instruction {
  1616  	i.opcode = OpcodeExtractlane
  1617  	i.v = x
  1618  	// We do not have a field for signedness, but `index` is a byte,
  1619  	// so we just encode the flag in the high bits of `u1`.
  1620  	i.u1 = uint64(index)
  1621  	if signed {
  1622  		i.u1 = i.u1 | 1<<32
  1623  	}
  1624  	i.u2 = uint64(lane)
  1625  	switch lane {
  1626  	case VecLaneI8x16, VecLaneI16x8, VecLaneI32x4:
  1627  		i.typ = TypeI32
  1628  	case VecLaneI64x2:
  1629  		i.typ = TypeI64
  1630  	case VecLaneF32x4:
  1631  		i.typ = TypeF32
  1632  	case VecLaneF64x2:
  1633  		i.typ = TypeF64
  1634  	}
  1635  	return i
  1636  }
  1637  
  1638  // AsInsertlane initializes this instruction as an insert lane instruction with OpcodeInsertlane on vector.
  1639  func (i *Instruction) AsInsertlane(x, y Value, index byte, lane VecLane) *Instruction {
  1640  	i.opcode = OpcodeInsertlane
  1641  	i.v = x
  1642  	i.v2 = y
  1643  	i.u1 = uint64(index)
  1644  	i.u2 = uint64(lane)
  1645  	i.typ = TypeV128
  1646  	return i
  1647  }
  1648  
  1649  // AsShuffle initializes this instruction as a shuffle instruction with OpcodeShuffle on vector.
  1650  func (i *Instruction) AsShuffle(x, y Value, lane []byte) *Instruction {
  1651  	i.opcode = OpcodeShuffle
  1652  	i.v = x
  1653  	i.v2 = y
  1654  	// Encode the 16 bytes as 8 bytes in u1, and 8 bytes in u2.
  1655  	i.u1 = uint64(lane[7])<<56 | uint64(lane[6])<<48 | uint64(lane[5])<<40 | uint64(lane[4])<<32 | uint64(lane[3])<<24 | uint64(lane[2])<<16 | uint64(lane[1])<<8 | uint64(lane[0])
  1656  	i.u2 = uint64(lane[15])<<56 | uint64(lane[14])<<48 | uint64(lane[13])<<40 | uint64(lane[12])<<32 | uint64(lane[11])<<24 | uint64(lane[10])<<16 | uint64(lane[9])<<8 | uint64(lane[8])
  1657  	i.typ = TypeV128
  1658  	return i
  1659  }
  1660  
  1661  // AsSwizzle initializes this instruction as an insert lane instruction with OpcodeSwizzle on vector.
  1662  func (i *Instruction) AsSwizzle(x, y Value, lane VecLane) *Instruction {
  1663  	i.opcode = OpcodeSwizzle
  1664  	i.v = x
  1665  	i.v2 = y
  1666  	i.u1 = uint64(lane)
  1667  	i.typ = TypeV128
  1668  	return i
  1669  }
  1670  
  1671  // AsSplat initializes this instruction as an insert lane instruction with OpcodeSplat on vector.
  1672  func (i *Instruction) AsSplat(x Value, lane VecLane) *Instruction {
  1673  	i.opcode = OpcodeSplat
  1674  	i.v = x
  1675  	i.u1 = uint64(lane)
  1676  	i.typ = TypeV128
  1677  	return i
  1678  }
  1679  
  1680  // AsRotl initializes this instruction as a word rotate left instruction with OpcodeRotl.
  1681  func (i *Instruction) AsRotl(x, amount Value) {
  1682  	i.opcode = OpcodeRotl
  1683  	i.v = x
  1684  	i.v2 = amount
  1685  	i.typ = x.Type()
  1686  }
  1687  
  1688  // AsRotr initializes this instruction as a word rotate right instruction with OpcodeRotr.
  1689  func (i *Instruction) AsRotr(x, amount Value) {
  1690  	i.opcode = OpcodeRotr
  1691  	i.v = x
  1692  	i.v2 = amount
  1693  	i.typ = x.Type()
  1694  }
  1695  
  1696  // IcmpData returns the operands and comparison condition of this integer comparison instruction.
  1697  func (i *Instruction) IcmpData() (x, y Value, c IntegerCmpCond) {
  1698  	return i.v, i.v2, IntegerCmpCond(i.u1)
  1699  }
  1700  
  1701  // FcmpData returns the operands and comparison condition of this floating-point comparison instruction.
  1702  func (i *Instruction) FcmpData() (x, y Value, c FloatCmpCond) {
  1703  	return i.v, i.v2, FloatCmpCond(i.u1)
  1704  }
  1705  
  1706  // VIcmpData returns the operands and comparison condition of this integer comparison instruction on vector.
  1707  func (i *Instruction) VIcmpData() (x, y Value, c IntegerCmpCond, l VecLane) {
  1708  	return i.v, i.v2, IntegerCmpCond(i.u1), VecLane(i.u2)
  1709  }
  1710  
  1711  // VFcmpData returns the operands and comparison condition of this float comparison instruction on vector.
  1712  func (i *Instruction) VFcmpData() (x, y Value, c FloatCmpCond, l VecLane) {
  1713  	return i.v, i.v2, FloatCmpCond(i.u1), VecLane(i.u2)
  1714  }
  1715  
  1716  // ExtractlaneData returns the operands and sign flag of Extractlane on vector.
  1717  func (i *Instruction) ExtractlaneData() (x Value, index byte, signed bool, l VecLane) {
  1718  	x = i.v
  1719  	index = byte(0b00001111 & i.u1)
  1720  	signed = i.u1>>32 != 0
  1721  	l = VecLane(i.u2)
  1722  	return
  1723  }
  1724  
  1725  // InsertlaneData returns the operands and sign flag of Insertlane on vector.
  1726  func (i *Instruction) InsertlaneData() (x, y Value, index byte, l VecLane) {
  1727  	x = i.v
  1728  	y = i.v2
  1729  	index = byte(i.u1)
  1730  	l = VecLane(i.u2)
  1731  	return
  1732  }
  1733  
  1734  // AsFadd initializes this instruction as a floating-point addition instruction with OpcodeFadd.
  1735  func (i *Instruction) AsFadd(x, y Value) {
  1736  	i.opcode = OpcodeFadd
  1737  	i.v = x
  1738  	i.v2 = y
  1739  	i.typ = x.Type()
  1740  }
  1741  
  1742  // AsFsub initializes this instruction as a floating-point subtraction instruction with OpcodeFsub.
  1743  func (i *Instruction) AsFsub(x, y Value) {
  1744  	i.opcode = OpcodeFsub
  1745  	i.v = x
  1746  	i.v2 = y
  1747  	i.typ = x.Type()
  1748  }
  1749  
  1750  // AsFmul initializes this instruction as a floating-point multiplication instruction with OpcodeFmul.
  1751  func (i *Instruction) AsFmul(x, y Value) {
  1752  	i.opcode = OpcodeFmul
  1753  	i.v = x
  1754  	i.v2 = y
  1755  	i.typ = x.Type()
  1756  }
  1757  
  1758  // AsFdiv initializes this instruction as a floating-point division instruction with OpcodeFdiv.
  1759  func (i *Instruction) AsFdiv(x, y Value) {
  1760  	i.opcode = OpcodeFdiv
  1761  	i.v = x
  1762  	i.v2 = y
  1763  	i.typ = x.Type()
  1764  }
  1765  
  1766  // AsFmin initializes this instruction to take the minimum of two floating-points with OpcodeFmin.
  1767  func (i *Instruction) AsFmin(x, y Value) {
  1768  	i.opcode = OpcodeFmin
  1769  	i.v = x
  1770  	i.v2 = y
  1771  	i.typ = x.Type()
  1772  }
  1773  
  1774  // AsFmax initializes this instruction to take the maximum of two floating-points with OpcodeFmax.
  1775  func (i *Instruction) AsFmax(x, y Value) {
  1776  	i.opcode = OpcodeFmax
  1777  	i.v = x
  1778  	i.v2 = y
  1779  	i.typ = x.Type()
  1780  }
  1781  
  1782  // AsF32const initializes this instruction as a 32-bit floating-point constant instruction with OpcodeF32const.
  1783  func (i *Instruction) AsF32const(f float32) *Instruction {
  1784  	i.opcode = OpcodeF32const
  1785  	i.typ = TypeF64
  1786  	i.u1 = uint64(math.Float32bits(f))
  1787  	return i
  1788  }
  1789  
  1790  // AsF64const initializes this instruction as a 64-bit floating-point constant instruction with OpcodeF64const.
  1791  func (i *Instruction) AsF64const(f float64) *Instruction {
  1792  	i.opcode = OpcodeF64const
  1793  	i.typ = TypeF64
  1794  	i.u1 = math.Float64bits(f)
  1795  	return i
  1796  }
  1797  
  1798  // AsVconst initializes this instruction as a vector constant instruction with OpcodeVconst.
  1799  func (i *Instruction) AsVconst(lo, hi uint64) *Instruction {
  1800  	i.opcode = OpcodeVconst
  1801  	i.typ = TypeV128
  1802  	i.u1 = lo
  1803  	i.u2 = hi
  1804  	return i
  1805  }
  1806  
  1807  // AsVbnot initializes this instruction as a vector negation instruction with OpcodeVbnot.
  1808  func (i *Instruction) AsVbnot(v Value) *Instruction {
  1809  	i.opcode = OpcodeVbnot
  1810  	i.typ = TypeV128
  1811  	i.v = v
  1812  	return i
  1813  }
  1814  
  1815  // AsVband initializes this instruction as an and vector instruction with OpcodeVband.
  1816  func (i *Instruction) AsVband(x, y Value) *Instruction {
  1817  	i.opcode = OpcodeVband
  1818  	i.typ = TypeV128
  1819  	i.v = x
  1820  	i.v2 = y
  1821  	return i
  1822  }
  1823  
  1824  // AsVbor initializes this instruction as an or vector instruction with OpcodeVbor.
  1825  func (i *Instruction) AsVbor(x, y Value) *Instruction {
  1826  	i.opcode = OpcodeVbor
  1827  	i.typ = TypeV128
  1828  	i.v = x
  1829  	i.v2 = y
  1830  	return i
  1831  }
  1832  
  1833  // AsVbxor initializes this instruction as a xor vector instruction with OpcodeVbxor.
  1834  func (i *Instruction) AsVbxor(x, y Value) *Instruction {
  1835  	i.opcode = OpcodeVbxor
  1836  	i.typ = TypeV128
  1837  	i.v = x
  1838  	i.v2 = y
  1839  	return i
  1840  }
  1841  
  1842  // AsVbandnot initializes this instruction as an and-not vector instruction with OpcodeVbandnot.
  1843  func (i *Instruction) AsVbandnot(x, y Value) *Instruction {
  1844  	i.opcode = OpcodeVbandnot
  1845  	i.typ = TypeV128
  1846  	i.v = x
  1847  	i.v2 = y
  1848  	return i
  1849  }
  1850  
  1851  // AsVbitselect initializes this instruction as a bit select vector instruction with OpcodeVbitselect.
  1852  func (i *Instruction) AsVbitselect(c, x, y Value) *Instruction {
  1853  	i.opcode = OpcodeVbitselect
  1854  	i.typ = TypeV128
  1855  	i.v = c
  1856  	i.v2 = x
  1857  	i.v3 = y
  1858  	return i
  1859  }
  1860  
  1861  // AsVanyTrue initializes this instruction as an anyTrue vector instruction with OpcodeVanyTrue.
  1862  func (i *Instruction) AsVanyTrue(x Value) *Instruction {
  1863  	i.opcode = OpcodeVanyTrue
  1864  	i.typ = TypeI32
  1865  	i.v = x
  1866  	return i
  1867  }
  1868  
  1869  // AsVallTrue initializes this instruction as an allTrue vector instruction with OpcodeVallTrue.
  1870  func (i *Instruction) AsVallTrue(x Value, lane VecLane) *Instruction {
  1871  	i.opcode = OpcodeVallTrue
  1872  	i.typ = TypeI32
  1873  	i.v = x
  1874  	i.u1 = uint64(lane)
  1875  	return i
  1876  }
  1877  
  1878  // AsVhighBits initializes this instruction as a highBits vector instruction with OpcodeVhighBits.
  1879  func (i *Instruction) AsVhighBits(x Value, lane VecLane) *Instruction {
  1880  	i.opcode = OpcodeVhighBits
  1881  	i.typ = TypeI32
  1882  	i.v = x
  1883  	i.u1 = uint64(lane)
  1884  	return i
  1885  }
  1886  
  1887  // VconstData returns the operands of this vector constant instruction.
  1888  func (i *Instruction) VconstData() (lo, hi uint64) {
  1889  	return i.u1, i.u2
  1890  }
  1891  
  1892  // AsReturn initializes this instruction as a return instruction with OpcodeReturn.
  1893  func (i *Instruction) AsReturn(vs []Value) *Instruction {
  1894  	i.opcode = OpcodeReturn
  1895  	i.vs = vs
  1896  	return i
  1897  }
  1898  
  1899  // AsIreduce initializes this instruction as a reduction instruction with OpcodeIreduce.
  1900  func (i *Instruction) AsIreduce(v Value, dstType Type) *Instruction {
  1901  	i.opcode = OpcodeIreduce
  1902  	i.v = v
  1903  	i.typ = dstType
  1904  	return i
  1905  }
  1906  
  1907  // AsWiden initializes this instruction as a signed or unsigned widen instruction
  1908  // on low half or high half of the given vector with OpcodeSwidenLow, OpcodeUwidenLow, OpcodeSwidenHigh, OpcodeUwidenHigh.
  1909  func (i *Instruction) AsWiden(v Value, lane VecLane, signed, low bool) *Instruction {
  1910  	switch {
  1911  	case signed && low:
  1912  		i.opcode = OpcodeSwidenLow
  1913  	case !signed && low:
  1914  		i.opcode = OpcodeUwidenLow
  1915  	case signed && !low:
  1916  		i.opcode = OpcodeSwidenHigh
  1917  	case !signed && !low:
  1918  		i.opcode = OpcodeUwidenHigh
  1919  	}
  1920  	i.v = v
  1921  	i.u1 = uint64(lane)
  1922  	return i
  1923  }
  1924  
  1925  // ReturnVals returns the return values of OpcodeReturn.
  1926  func (i *Instruction) ReturnVals() []Value {
  1927  	return i.vs
  1928  }
  1929  
  1930  // AsExitWithCode initializes this instruction as a trap instruction with OpcodeExitWithCode.
  1931  func (i *Instruction) AsExitWithCode(ctx Value, code wazevoapi.ExitCode) {
  1932  	i.opcode = OpcodeExitWithCode
  1933  	i.v = ctx
  1934  	i.u1 = uint64(code)
  1935  }
  1936  
  1937  // AsExitIfTrueWithCode initializes this instruction as a trap instruction with OpcodeExitIfTrueWithCode.
  1938  func (i *Instruction) AsExitIfTrueWithCode(ctx, c Value, code wazevoapi.ExitCode) *Instruction {
  1939  	i.opcode = OpcodeExitIfTrueWithCode
  1940  	i.v = ctx
  1941  	i.v2 = c
  1942  	i.u1 = uint64(code)
  1943  	return i
  1944  }
  1945  
  1946  // ExitWithCodeData returns the context and exit code of OpcodeExitWithCode.
  1947  func (i *Instruction) ExitWithCodeData() (ctx Value, code wazevoapi.ExitCode) {
  1948  	return i.v, wazevoapi.ExitCode(i.u1)
  1949  }
  1950  
  1951  // ExitIfTrueWithCodeData returns the context and exit code of OpcodeExitWithCode.
  1952  func (i *Instruction) ExitIfTrueWithCodeData() (ctx, c Value, code wazevoapi.ExitCode) {
  1953  	return i.v, i.v2, wazevoapi.ExitCode(i.u1)
  1954  }
  1955  
  1956  // InvertBrx inverts either OpcodeBrz or OpcodeBrnz to the other.
  1957  func (i *Instruction) InvertBrx() {
  1958  	switch i.opcode {
  1959  	case OpcodeBrz:
  1960  		i.opcode = OpcodeBrnz
  1961  	case OpcodeBrnz:
  1962  		i.opcode = OpcodeBrz
  1963  	default:
  1964  		panic("BUG")
  1965  	}
  1966  }
  1967  
  1968  // BranchData returns the branch data for this instruction necessary for backends.
  1969  func (i *Instruction) BranchData() (condVal Value, blockArgs []Value, target BasicBlock) {
  1970  	switch i.opcode {
  1971  	case OpcodeJump:
  1972  		condVal = ValueInvalid
  1973  	case OpcodeBrz, OpcodeBrnz:
  1974  		condVal = i.v
  1975  	default:
  1976  		panic("BUG")
  1977  	}
  1978  	blockArgs = i.vs
  1979  	target = i.blk
  1980  	return
  1981  }
  1982  
  1983  // BrTableData returns the branch table data for this instruction necessary for backends.
  1984  func (i *Instruction) BrTableData() (index Value, targets []BasicBlock) {
  1985  	if i.opcode != OpcodeBrTable {
  1986  		panic("BUG: BrTableData only available for OpcodeBrTable")
  1987  	}
  1988  	index = i.v
  1989  	targets = i.targets
  1990  	return
  1991  }
  1992  
  1993  // AsJump initializes this instruction as a jump instruction with OpcodeJump.
  1994  func (i *Instruction) AsJump(vs []Value, target BasicBlock) {
  1995  	i.opcode = OpcodeJump
  1996  	i.vs = vs
  1997  	i.blk = target
  1998  }
  1999  
  2000  // IsFallthroughJump returns true if this instruction is a fallthrough jump.
  2001  func (i *Instruction) IsFallthroughJump() bool {
  2002  	if i.opcode != OpcodeJump {
  2003  		panic("BUG: IsFallthrough only available for OpcodeJump")
  2004  	}
  2005  	return i.opcode == OpcodeJump && i.u1 != 0
  2006  }
  2007  
  2008  // AsFallthroughJump marks this instruction as a fallthrough jump.
  2009  func (i *Instruction) AsFallthroughJump() {
  2010  	if i.opcode != OpcodeJump {
  2011  		panic("BUG: AsFallthroughJump only available for OpcodeJump")
  2012  	}
  2013  	i.u1 = 1
  2014  }
  2015  
  2016  // AsBrz initializes this instruction as a branch-if-zero instruction with OpcodeBrz.
  2017  func (i *Instruction) AsBrz(v Value, args []Value, target BasicBlock) {
  2018  	i.opcode = OpcodeBrz
  2019  	i.v = v
  2020  	i.vs = args
  2021  	i.blk = target
  2022  }
  2023  
  2024  // AsBrnz initializes this instruction as a branch-if-not-zero instruction with OpcodeBrnz.
  2025  func (i *Instruction) AsBrnz(v Value, args []Value, target BasicBlock) *Instruction {
  2026  	i.opcode = OpcodeBrnz
  2027  	i.v = v
  2028  	i.vs = args
  2029  	i.blk = target
  2030  	return i
  2031  }
  2032  
  2033  // AsBrTable initializes this instruction as a branch-table instruction with OpcodeBrTable.
  2034  func (i *Instruction) AsBrTable(index Value, targets []BasicBlock) {
  2035  	i.opcode = OpcodeBrTable
  2036  	i.v = index
  2037  	i.targets = targets
  2038  }
  2039  
  2040  // AsCall initializes this instruction as a call instruction with OpcodeCall.
  2041  func (i *Instruction) AsCall(ref FuncRef, sig *Signature, args []Value) {
  2042  	i.opcode = OpcodeCall
  2043  	i.u1 = uint64(ref)
  2044  	i.vs = args
  2045  	i.u2 = uint64(sig.ID)
  2046  	sig.used = true
  2047  }
  2048  
  2049  // CallData returns the call data for this instruction necessary for backends.
  2050  func (i *Instruction) CallData() (ref FuncRef, sigID SignatureID, args []Value) {
  2051  	if i.opcode != OpcodeCall {
  2052  		panic("BUG: CallData only available for OpcodeCall")
  2053  	}
  2054  	ref = FuncRef(i.u1)
  2055  	sigID = SignatureID(i.u2)
  2056  	args = i.vs
  2057  	return
  2058  }
  2059  
  2060  // AsCallIndirect initializes this instruction as a call-indirect instruction with OpcodeCallIndirect.
  2061  func (i *Instruction) AsCallIndirect(funcPtr Value, sig *Signature, args []Value) *Instruction {
  2062  	i.opcode = OpcodeCallIndirect
  2063  	i.typ = TypeF64
  2064  	i.vs = args
  2065  	i.v = funcPtr
  2066  	i.u1 = uint64(sig.ID)
  2067  	sig.used = true
  2068  	return i
  2069  }
  2070  
  2071  // CallIndirectData returns the call indirect data for this instruction necessary for backends.
  2072  func (i *Instruction) CallIndirectData() (funcPtr Value, sigID SignatureID, args []Value) {
  2073  	if i.opcode != OpcodeCallIndirect {
  2074  		panic("BUG: CallIndirectData only available for OpcodeCallIndirect")
  2075  	}
  2076  	funcPtr = i.v
  2077  	sigID = SignatureID(i.u1)
  2078  	args = i.vs
  2079  	return
  2080  }
  2081  
  2082  // AsClz initializes this instruction as a Count Leading Zeroes instruction with OpcodeClz.
  2083  func (i *Instruction) AsClz(x Value) {
  2084  	i.opcode = OpcodeClz
  2085  	i.v = x
  2086  	i.typ = x.Type()
  2087  }
  2088  
  2089  // AsCtz initializes this instruction as a Count Trailing Zeroes instruction with OpcodeCtz.
  2090  func (i *Instruction) AsCtz(x Value) {
  2091  	i.opcode = OpcodeCtz
  2092  	i.v = x
  2093  	i.typ = x.Type()
  2094  }
  2095  
  2096  // AsPopcnt initializes this instruction as a Population Count instruction with OpcodePopcnt.
  2097  func (i *Instruction) AsPopcnt(x Value) {
  2098  	i.opcode = OpcodePopcnt
  2099  	i.v = x
  2100  	i.typ = x.Type()
  2101  }
  2102  
  2103  // AsFneg initializes this instruction as an instruction with OpcodeFneg.
  2104  func (i *Instruction) AsFneg(x Value) *Instruction {
  2105  	i.opcode = OpcodeFneg
  2106  	i.v = x
  2107  	i.typ = x.Type()
  2108  	return i
  2109  }
  2110  
  2111  // AsSqrt initializes this instruction as an instruction with OpcodeSqrt.
  2112  func (i *Instruction) AsSqrt(x Value) *Instruction {
  2113  	i.opcode = OpcodeSqrt
  2114  	i.v = x
  2115  	i.typ = x.Type()
  2116  	return i
  2117  }
  2118  
  2119  // AsFabs initializes this instruction as an instruction with OpcodeFabs.
  2120  func (i *Instruction) AsFabs(x Value) *Instruction {
  2121  	i.opcode = OpcodeFabs
  2122  	i.v = x
  2123  	i.typ = x.Type()
  2124  	return i
  2125  }
  2126  
  2127  // AsFcopysign initializes this instruction as an instruction with OpcodeFcopysign.
  2128  func (i *Instruction) AsFcopysign(x, y Value) *Instruction {
  2129  	i.opcode = OpcodeFcopysign
  2130  	i.v = x
  2131  	i.v2 = y
  2132  	i.typ = x.Type()
  2133  	return i
  2134  }
  2135  
  2136  // AsCeil initializes this instruction as an instruction with OpcodeCeil.
  2137  func (i *Instruction) AsCeil(x Value) *Instruction {
  2138  	i.opcode = OpcodeCeil
  2139  	i.v = x
  2140  	i.typ = x.Type()
  2141  	return i
  2142  }
  2143  
  2144  // AsFloor initializes this instruction as an instruction with OpcodeFloor.
  2145  func (i *Instruction) AsFloor(x Value) *Instruction {
  2146  	i.opcode = OpcodeFloor
  2147  	i.v = x
  2148  	i.typ = x.Type()
  2149  	return i
  2150  }
  2151  
  2152  // AsTrunc initializes this instruction as an instruction with OpcodeTrunc.
  2153  func (i *Instruction) AsTrunc(x Value) *Instruction {
  2154  	i.opcode = OpcodeTrunc
  2155  	i.v = x
  2156  	i.typ = x.Type()
  2157  	return i
  2158  }
  2159  
  2160  // AsNearest initializes this instruction as an instruction with OpcodeNearest.
  2161  func (i *Instruction) AsNearest(x Value) *Instruction {
  2162  	i.opcode = OpcodeNearest
  2163  	i.v = x
  2164  	i.typ = x.Type()
  2165  	return i
  2166  }
  2167  
  2168  // AsBitcast initializes this instruction as an instruction with OpcodeBitcast.
  2169  func (i *Instruction) AsBitcast(x Value, dstType Type) *Instruction {
  2170  	i.opcode = OpcodeBitcast
  2171  	i.v = x
  2172  	i.typ = dstType
  2173  	return i
  2174  }
  2175  
  2176  // BitcastData returns the operands for a bitcast instruction.
  2177  func (i *Instruction) BitcastData() (x Value, dstType Type) {
  2178  	return i.v, i.typ
  2179  }
  2180  
  2181  // AsFdemote initializes this instruction as an instruction with OpcodeFdemote.
  2182  func (i *Instruction) AsFdemote(x Value) {
  2183  	i.opcode = OpcodeFdemote
  2184  	i.v = x
  2185  	i.typ = TypeF32
  2186  }
  2187  
  2188  // AsFpromote initializes this instruction as an instruction with OpcodeFpromote.
  2189  func (i *Instruction) AsFpromote(x Value) {
  2190  	i.opcode = OpcodeFpromote
  2191  	i.v = x
  2192  	i.typ = TypeF64
  2193  }
  2194  
  2195  // AsFcvtFromInt initializes this instruction as an instruction with either OpcodeFcvtFromUint or OpcodeFcvtFromSint
  2196  func (i *Instruction) AsFcvtFromInt(x Value, signed bool, dst64bit bool) *Instruction {
  2197  	if signed {
  2198  		i.opcode = OpcodeFcvtFromSint
  2199  	} else {
  2200  		i.opcode = OpcodeFcvtFromUint
  2201  	}
  2202  	i.v = x
  2203  	if dst64bit {
  2204  		i.typ = TypeF64
  2205  	} else {
  2206  		i.typ = TypeF32
  2207  	}
  2208  	return i
  2209  }
  2210  
  2211  // AsFcvtToInt initializes this instruction as an instruction with either OpcodeFcvtToUint or OpcodeFcvtToSint
  2212  func (i *Instruction) AsFcvtToInt(x, ctx Value, signed bool, dst64bit bool, sat bool) *Instruction {
  2213  	switch {
  2214  	case signed && !sat:
  2215  		i.opcode = OpcodeFcvtToSint
  2216  	case !signed && !sat:
  2217  		i.opcode = OpcodeFcvtToUint
  2218  	case signed && sat:
  2219  		i.opcode = OpcodeFcvtToSintSat
  2220  	case !signed && sat:
  2221  		i.opcode = OpcodeFcvtToUintSat
  2222  	}
  2223  	i.v = x
  2224  	i.v2 = ctx
  2225  	if dst64bit {
  2226  		i.typ = TypeI64
  2227  	} else {
  2228  		i.typ = TypeI32
  2229  	}
  2230  	return i
  2231  }
  2232  
  2233  // AsVFcvtToIntSat initializes this instruction as an instruction with either OpcodeVFcvtToSintSat or OpcodeVFcvtToUintSat
  2234  func (i *Instruction) AsVFcvtToIntSat(x Value, lane VecLane, signed bool) *Instruction {
  2235  	if signed {
  2236  		i.opcode = OpcodeVFcvtToSintSat
  2237  	} else {
  2238  		i.opcode = OpcodeVFcvtToUintSat
  2239  	}
  2240  	i.v = x
  2241  	i.u1 = uint64(lane)
  2242  	return i
  2243  }
  2244  
  2245  // AsVFcvtFromInt initializes this instruction as an instruction with either OpcodeVFcvtToSintSat or OpcodeVFcvtToUintSat
  2246  func (i *Instruction) AsVFcvtFromInt(x Value, lane VecLane, signed bool) *Instruction {
  2247  	if signed {
  2248  		i.opcode = OpcodeVFcvtFromSint
  2249  	} else {
  2250  		i.opcode = OpcodeVFcvtFromUint
  2251  	}
  2252  	i.v = x
  2253  	i.u1 = uint64(lane)
  2254  	return i
  2255  }
  2256  
  2257  // AsNarrow initializes this instruction as an instruction with either OpcodeSnarrow or OpcodeUnarrow
  2258  func (i *Instruction) AsNarrow(x, y Value, lane VecLane, signed bool) *Instruction {
  2259  	if signed {
  2260  		i.opcode = OpcodeSnarrow
  2261  	} else {
  2262  		i.opcode = OpcodeUnarrow
  2263  	}
  2264  	i.v = x
  2265  	i.v2 = y
  2266  	i.u1 = uint64(lane)
  2267  	return i
  2268  }
  2269  
  2270  // AsFvpromoteLow initializes this instruction as an instruction with OpcodeFvpromoteLow
  2271  func (i *Instruction) AsFvpromoteLow(x Value, lane VecLane) *Instruction {
  2272  	i.opcode = OpcodeFvpromoteLow
  2273  	i.v = x
  2274  	i.u1 = uint64(lane)
  2275  	return i
  2276  }
  2277  
  2278  // AsFvdemote initializes this instruction as an instruction with OpcodeFvdemote
  2279  func (i *Instruction) AsFvdemote(x Value, lane VecLane) *Instruction {
  2280  	i.opcode = OpcodeFvdemote
  2281  	i.v = x
  2282  	i.u1 = uint64(lane)
  2283  	return i
  2284  }
  2285  
  2286  // AsSExtend initializes this instruction as a sign extension instruction with OpcodeSExtend.
  2287  func (i *Instruction) AsSExtend(v Value, from, to byte) *Instruction {
  2288  	i.opcode = OpcodeSExtend
  2289  	i.v = v
  2290  	i.u1 = uint64(from)<<8 | uint64(to)
  2291  	if to == 64 {
  2292  		i.typ = TypeI64
  2293  	} else {
  2294  		i.typ = TypeI32
  2295  	}
  2296  	return i
  2297  }
  2298  
  2299  // AsUExtend initializes this instruction as an unsigned extension instruction with OpcodeUExtend.
  2300  func (i *Instruction) AsUExtend(v Value, from, to byte) *Instruction {
  2301  	i.opcode = OpcodeUExtend
  2302  	i.v = v
  2303  	i.u1 = uint64(from)<<8 | uint64(to)
  2304  	if to == 64 {
  2305  		i.typ = TypeI64
  2306  	} else {
  2307  		i.typ = TypeI32
  2308  	}
  2309  	return i
  2310  }
  2311  
  2312  func (i *Instruction) ExtendData() (from, to byte, signed bool) {
  2313  	if i.opcode != OpcodeSExtend && i.opcode != OpcodeUExtend {
  2314  		panic("BUG: ExtendData only available for OpcodeSExtend and OpcodeUExtend")
  2315  	}
  2316  	from = byte(i.u1 >> 8)
  2317  	to = byte(i.u1)
  2318  	signed = i.opcode == OpcodeSExtend
  2319  	return
  2320  }
  2321  
  2322  // AsSelect initializes this instruction as an unsigned extension instruction with OpcodeSelect.
  2323  func (i *Instruction) AsSelect(c, x, y Value) *Instruction {
  2324  	i.opcode = OpcodeSelect
  2325  	i.v = c
  2326  	i.v2 = x
  2327  	i.v3 = y
  2328  	i.typ = x.Type()
  2329  	return i
  2330  }
  2331  
  2332  // SelectData returns the select data for this instruction necessary for backends.
  2333  func (i *Instruction) SelectData() (c, x, y Value) {
  2334  	c = i.v
  2335  	x = i.v2
  2336  	y = i.v3
  2337  	return
  2338  }
  2339  
  2340  // ExtendFromToBits returns the from and to bit size for the extension instruction.
  2341  func (i *Instruction) ExtendFromToBits() (from, to byte) {
  2342  	from = byte(i.u1 >> 8)
  2343  	to = byte(i.u1)
  2344  	return
  2345  }
  2346  
  2347  // Format returns a string representation of this instruction with the given builder.
  2348  // For debugging purposes only.
  2349  func (i *Instruction) Format(b Builder) string {
  2350  	var instSuffix string
  2351  	switch i.opcode {
  2352  	case OpcodeExitWithCode:
  2353  		instSuffix = fmt.Sprintf(" %s, %s", i.v.Format(b), wazevoapi.ExitCode(i.u1))
  2354  	case OpcodeExitIfTrueWithCode:
  2355  		instSuffix = fmt.Sprintf(" %s, %s, %s", i.v2.Format(b), i.v.Format(b), wazevoapi.ExitCode(i.u1))
  2356  	case OpcodeIadd, OpcodeIsub, OpcodeImul, OpcodeFadd, OpcodeFsub, OpcodeFmin, OpcodeFmax, OpcodeFdiv, OpcodeFmul:
  2357  		instSuffix = fmt.Sprintf(" %s, %s", i.v.Format(b), i.v2.Format(b))
  2358  	case OpcodeIcmp:
  2359  		instSuffix = fmt.Sprintf(" %s, %s, %s", IntegerCmpCond(i.u1), i.v.Format(b), i.v2.Format(b))
  2360  	case OpcodeFcmp:
  2361  		instSuffix = fmt.Sprintf(" %s, %s, %s", FloatCmpCond(i.u1), i.v.Format(b), i.v2.Format(b))
  2362  	case OpcodeSExtend, OpcodeUExtend:
  2363  		instSuffix = fmt.Sprintf(" %s, %d->%d", i.v.Format(b), i.u1>>8, i.u1&0xff)
  2364  	case OpcodeCall, OpcodeCallIndirect:
  2365  		vs := make([]string, len(i.vs))
  2366  		for idx := range vs {
  2367  			vs[idx] = i.vs[idx].Format(b)
  2368  		}
  2369  		if i.opcode == OpcodeCallIndirect {
  2370  			instSuffix = fmt.Sprintf(" %s:%s, %s", i.v.Format(b), SignatureID(i.u1), strings.Join(vs, ", "))
  2371  		} else {
  2372  			instSuffix = fmt.Sprintf(" %s:%s, %s", FuncRef(i.u1), SignatureID(i.u2), strings.Join(vs, ", "))
  2373  		}
  2374  	case OpcodeStore, OpcodeIstore8, OpcodeIstore16, OpcodeIstore32:
  2375  		instSuffix = fmt.Sprintf(" %s, %s, %#x", i.v.Format(b), i.v2.Format(b), int32(i.u1))
  2376  	case OpcodeLoad, OpcodeVZeroExtLoad:
  2377  		instSuffix = fmt.Sprintf(" %s, %#x", i.v.Format(b), int32(i.u1))
  2378  	case OpcodeLoadSplat:
  2379  		instSuffix = fmt.Sprintf(".%s %s, %#x", VecLane(i.u2), i.v.Format(b), int32(i.u1))
  2380  	case OpcodeUload8, OpcodeUload16, OpcodeUload32, OpcodeSload8, OpcodeSload16, OpcodeSload32:
  2381  		instSuffix = fmt.Sprintf(" %s, %#x", i.v.Format(b), int32(i.u1))
  2382  	case OpcodeSelect, OpcodeVbitselect:
  2383  		instSuffix = fmt.Sprintf(" %s, %s, %s", i.v.Format(b), i.v2.Format(b), i.v3.Format(b))
  2384  	case OpcodeIconst:
  2385  		switch i.typ {
  2386  		case TypeI32:
  2387  			instSuffix = fmt.Sprintf("_32 %#x", uint32(i.u1))
  2388  		case TypeI64:
  2389  			instSuffix = fmt.Sprintf("_64 %#x", i.u1)
  2390  		}
  2391  	case OpcodeVconst:
  2392  		instSuffix = fmt.Sprintf(" %016x %016x", i.u1, i.u2)
  2393  	case OpcodeF32const:
  2394  		instSuffix = fmt.Sprintf(" %f", math.Float32frombits(uint32(i.u1)))
  2395  	case OpcodeF64const:
  2396  		instSuffix = fmt.Sprintf(" %f", math.Float64frombits(i.u1))
  2397  	case OpcodeReturn:
  2398  		if len(i.vs) == 0 {
  2399  			break
  2400  		}
  2401  		vs := make([]string, len(i.vs))
  2402  		for idx := range vs {
  2403  			vs[idx] = i.vs[idx].Format(b)
  2404  		}
  2405  		instSuffix = fmt.Sprintf(" %s", strings.Join(vs, ", "))
  2406  	case OpcodeJump:
  2407  		vs := make([]string, len(i.vs)+1)
  2408  		if i.IsFallthroughJump() {
  2409  			vs[0] = " fallthrough"
  2410  		} else {
  2411  			vs[0] = " " + i.blk.(*basicBlock).Name()
  2412  		}
  2413  		for idx := range i.vs {
  2414  			vs[idx+1] = i.vs[idx].Format(b)
  2415  		}
  2416  
  2417  		instSuffix = strings.Join(vs, ", ")
  2418  	case OpcodeBrz, OpcodeBrnz:
  2419  		vs := make([]string, len(i.vs)+2)
  2420  		vs[0] = " " + i.v.Format(b)
  2421  		vs[1] = i.blk.(*basicBlock).Name()
  2422  		for idx := range i.vs {
  2423  			vs[idx+2] = i.vs[idx].Format(b)
  2424  		}
  2425  		instSuffix = strings.Join(vs, ", ")
  2426  	case OpcodeBrTable:
  2427  		// `BrTable index, [label1, label2, ... labelN]`
  2428  		instSuffix = fmt.Sprintf(" %s", i.v.Format(b))
  2429  		instSuffix += ", ["
  2430  		for i, target := range i.targets {
  2431  			blk := target.(*basicBlock)
  2432  			if i == 0 {
  2433  				instSuffix += blk.Name()
  2434  			} else {
  2435  				instSuffix += ", " + blk.Name()
  2436  			}
  2437  		}
  2438  		instSuffix += "]"
  2439  	case OpcodeBand, OpcodeBor, OpcodeBxor, OpcodeRotr, OpcodeRotl, OpcodeIshl, OpcodeSshr, OpcodeUshr,
  2440  		OpcodeSdiv, OpcodeUdiv, OpcodeFcopysign, OpcodeSrem, OpcodeUrem,
  2441  		OpcodeVbnot, OpcodeVbxor, OpcodeVbor, OpcodeVband, OpcodeVbandnot, OpcodeVIcmp, OpcodeVFcmp:
  2442  		instSuffix = fmt.Sprintf(" %s, %s", i.v.Format(b), i.v2.Format(b))
  2443  	case OpcodeUndefined:
  2444  	case OpcodeClz, OpcodeCtz, OpcodePopcnt, OpcodeFneg, OpcodeFcvtToSint, OpcodeFcvtToUint, OpcodeFcvtFromSint,
  2445  		OpcodeFcvtFromUint, OpcodeFcvtToSintSat, OpcodeFcvtToUintSat, OpcodeFdemote, OpcodeFpromote, OpcodeIreduce, OpcodeBitcast, OpcodeSqrt, OpcodeFabs,
  2446  		OpcodeCeil, OpcodeFloor, OpcodeTrunc, OpcodeNearest:
  2447  		instSuffix = " " + i.v.Format(b)
  2448  	case OpcodeVIadd, OpcodeIaddPairwise, OpcodeVSaddSat, OpcodeVUaddSat, OpcodeVIsub, OpcodeVSsubSat, OpcodeVUsubSat,
  2449  		OpcodeVImin, OpcodeVUmin, OpcodeVImax, OpcodeVUmax, OpcodeVImul, OpcodeVAvgRound,
  2450  		OpcodeVFadd, OpcodeVFsub, OpcodeVFmul, OpcodeVFdiv,
  2451  		OpcodeVIshl, OpcodeVSshr, OpcodeVUshr,
  2452  		OpcodeVFmin, OpcodeVFmax, OpcodeVMinPseudo, OpcodeVMaxPseudo,
  2453  		OpcodeSnarrow, OpcodeUnarrow, OpcodeSwizzle, OpcodeSqmulRoundSat:
  2454  		instSuffix = fmt.Sprintf(".%s %s, %s", VecLane(i.u1), i.v.Format(b), i.v2.Format(b))
  2455  	case OpcodeVIabs, OpcodeVIneg, OpcodeVIpopcnt, OpcodeVhighBits, OpcodeVallTrue, OpcodeVanyTrue,
  2456  		OpcodeVFabs, OpcodeVFneg, OpcodeVSqrt, OpcodeVCeil, OpcodeVFloor, OpcodeVTrunc, OpcodeVNearest,
  2457  		OpcodeVFcvtToUintSat, OpcodeVFcvtToSintSat, OpcodeVFcvtFromUint, OpcodeVFcvtFromSint,
  2458  		OpcodeFvpromoteLow, OpcodeFvdemote, OpcodeSwidenLow, OpcodeUwidenLow, OpcodeSwidenHigh, OpcodeUwidenHigh,
  2459  		OpcodeSplat:
  2460  		instSuffix = fmt.Sprintf(".%s %s", VecLane(i.u1), i.v.Format(b))
  2461  	case OpcodeExtractlane:
  2462  		var signedness string
  2463  		if i.u1 != 0 {
  2464  			signedness = "signed"
  2465  		} else {
  2466  			signedness = "unsigned"
  2467  		}
  2468  		instSuffix = fmt.Sprintf(".%s %d, %s (%s)", VecLane(i.u2), 0x0000FFFF&i.u1, i.v.Format(b), signedness)
  2469  	case OpcodeInsertlane:
  2470  		instSuffix = fmt.Sprintf(".%s %d, %s, %s", VecLane(i.u2), i.u1, i.v.Format(b), i.v2.Format(b))
  2471  	case OpcodeShuffle:
  2472  		lanes := make([]byte, 16)
  2473  		for idx := 0; idx < 8; idx++ {
  2474  			lanes[idx] = byte(i.u1 >> (8 * idx))
  2475  		}
  2476  		for idx := 0; idx < 8; idx++ {
  2477  			lanes[idx+8] = byte(i.u2 >> (8 * idx))
  2478  		}
  2479  		// Prints Shuffle.[0 1 2 3 4 5 6 7 ...] v2, v3
  2480  		instSuffix = fmt.Sprintf(".%v %s, %s", lanes, i.v.Format(b), i.v2.Format(b))
  2481  
  2482  	default:
  2483  		panic(fmt.Sprintf("TODO: format for %s", i.opcode))
  2484  	}
  2485  
  2486  	instr := i.opcode.String() + instSuffix
  2487  
  2488  	var rvs []string
  2489  	if rv := i.rValue; rv.Valid() {
  2490  		rvs = append(rvs, rv.formatWithType(b))
  2491  	}
  2492  
  2493  	for _, v := range i.rValues {
  2494  		rvs = append(rvs, v.formatWithType(b))
  2495  	}
  2496  
  2497  	if len(rvs) > 0 {
  2498  		return fmt.Sprintf("%s = %s", strings.Join(rvs, ", "), instr)
  2499  	} else {
  2500  		return instr
  2501  	}
  2502  }
  2503  
  2504  // addArgumentBranchInst adds an argument to this instruction.
  2505  func (i *Instruction) addArgumentBranchInst(v Value) {
  2506  	switch i.opcode {
  2507  	case OpcodeJump, OpcodeBrz, OpcodeBrnz:
  2508  		i.vs = append(i.vs, v)
  2509  	default:
  2510  		panic("BUG: " + i.opcode.String())
  2511  	}
  2512  }
  2513  
  2514  // Constant returns true if this instruction is a constant instruction.
  2515  func (i *Instruction) Constant() bool {
  2516  	switch i.opcode {
  2517  	case OpcodeIconst, OpcodeF32const, OpcodeF64const:
  2518  		return true
  2519  	}
  2520  	return false
  2521  }
  2522  
  2523  // ConstantVal returns the constant value of this instruction.
  2524  // How to interpret the return value depends on the opcode.
  2525  func (i *Instruction) ConstantVal() (ret uint64) {
  2526  	switch i.opcode {
  2527  	case OpcodeIconst, OpcodeF32const, OpcodeF64const:
  2528  		ret = i.u1
  2529  	default:
  2530  		panic("TODO")
  2531  	}
  2532  	return
  2533  }
  2534  
  2535  // String implements fmt.Stringer.
  2536  func (o Opcode) String() (ret string) {
  2537  	switch o {
  2538  	case OpcodeInvalid:
  2539  		return "invalid"
  2540  	case OpcodeUndefined:
  2541  		return "Undefined"
  2542  	case OpcodeJump:
  2543  		return "Jump"
  2544  	case OpcodeBrz:
  2545  		return "Brz"
  2546  	case OpcodeBrnz:
  2547  		return "Brnz"
  2548  	case OpcodeBrTable:
  2549  		return "BrTable"
  2550  	case OpcodeExitWithCode:
  2551  		return "Exit"
  2552  	case OpcodeExitIfTrueWithCode:
  2553  		return "ExitIfTrue"
  2554  	case OpcodeReturn:
  2555  		return "Return"
  2556  	case OpcodeCall:
  2557  		return "Call"
  2558  	case OpcodeCallIndirect:
  2559  		return "CallIndirect"
  2560  	case OpcodeSplat:
  2561  		return "Splat"
  2562  	case OpcodeSwizzle:
  2563  		return "Swizzle"
  2564  	case OpcodeInsertlane:
  2565  		return "Insertlane"
  2566  	case OpcodeExtractlane:
  2567  		return "Extractlane"
  2568  	case OpcodeLoad:
  2569  		return "Load"
  2570  	case OpcodeLoadSplat:
  2571  		return "LoadSplat"
  2572  	case OpcodeStore:
  2573  		return "Store"
  2574  	case OpcodeUload8:
  2575  		return "Uload8"
  2576  	case OpcodeSload8:
  2577  		return "Sload8"
  2578  	case OpcodeIstore8:
  2579  		return "Istore8"
  2580  	case OpcodeUload16:
  2581  		return "Uload16"
  2582  	case OpcodeSload16:
  2583  		return "Sload16"
  2584  	case OpcodeIstore16:
  2585  		return "Istore16"
  2586  	case OpcodeUload32:
  2587  		return "Uload32"
  2588  	case OpcodeSload32:
  2589  		return "Sload32"
  2590  	case OpcodeIstore32:
  2591  		return "Istore32"
  2592  	case OpcodeIconst:
  2593  		return "Iconst"
  2594  	case OpcodeF32const:
  2595  		return "F32const"
  2596  	case OpcodeF64const:
  2597  		return "F64const"
  2598  	case OpcodeVconst:
  2599  		return "Vconst"
  2600  	case OpcodeShuffle:
  2601  		return "Shuffle"
  2602  	case OpcodeSelect:
  2603  		return "Select"
  2604  	case OpcodeVanyTrue:
  2605  		return "VanyTrue"
  2606  	case OpcodeVallTrue:
  2607  		return "VallTrue"
  2608  	case OpcodeVhighBits:
  2609  		return "VhighBits"
  2610  	case OpcodeIcmp:
  2611  		return "Icmp"
  2612  	case OpcodeIcmpImm:
  2613  		return "IcmpImm"
  2614  	case OpcodeVIcmp:
  2615  		return "VIcmp"
  2616  	case OpcodeIadd:
  2617  		return "Iadd"
  2618  	case OpcodeIsub:
  2619  		return "Isub"
  2620  	case OpcodeImul:
  2621  		return "Imul"
  2622  	case OpcodeUdiv:
  2623  		return "Udiv"
  2624  	case OpcodeSdiv:
  2625  		return "Sdiv"
  2626  	case OpcodeUrem:
  2627  		return "Urem"
  2628  	case OpcodeSrem:
  2629  		return "Srem"
  2630  	case OpcodeBand:
  2631  		return "Band"
  2632  	case OpcodeBor:
  2633  		return "Bor"
  2634  	case OpcodeBxor:
  2635  		return "Bxor"
  2636  	case OpcodeBnot:
  2637  		return "Bnot"
  2638  	case OpcodeRotl:
  2639  		return "Rotl"
  2640  	case OpcodeRotr:
  2641  		return "Rotr"
  2642  	case OpcodeIshl:
  2643  		return "Ishl"
  2644  	case OpcodeUshr:
  2645  		return "Ushr"
  2646  	case OpcodeSshr:
  2647  		return "Sshr"
  2648  	case OpcodeClz:
  2649  		return "Clz"
  2650  	case OpcodeCtz:
  2651  		return "Ctz"
  2652  	case OpcodePopcnt:
  2653  		return "Popcnt"
  2654  	case OpcodeFcmp:
  2655  		return "Fcmp"
  2656  	case OpcodeFadd:
  2657  		return "Fadd"
  2658  	case OpcodeFsub:
  2659  		return "Fsub"
  2660  	case OpcodeFmul:
  2661  		return "Fmul"
  2662  	case OpcodeFdiv:
  2663  		return "Fdiv"
  2664  	case OpcodeSqmulRoundSat:
  2665  		return "SqmulRoundSat"
  2666  	case OpcodeSqrt:
  2667  		return "Sqrt"
  2668  	case OpcodeFneg:
  2669  		return "Fneg"
  2670  	case OpcodeFabs:
  2671  		return "Fabs"
  2672  	case OpcodeFcopysign:
  2673  		return "Fcopysign"
  2674  	case OpcodeFmin:
  2675  		return "Fmin"
  2676  	case OpcodeFmax:
  2677  		return "Fmax"
  2678  	case OpcodeCeil:
  2679  		return "Ceil"
  2680  	case OpcodeFloor:
  2681  		return "Floor"
  2682  	case OpcodeTrunc:
  2683  		return "Trunc"
  2684  	case OpcodeNearest:
  2685  		return "Nearest"
  2686  	case OpcodeBitcast:
  2687  		return "Bitcast"
  2688  	case OpcodeBmask:
  2689  		return "Bmask"
  2690  	case OpcodeIreduce:
  2691  		return "Ireduce"
  2692  	case OpcodeSnarrow:
  2693  		return "Snarrow"
  2694  	case OpcodeUnarrow:
  2695  		return "Unarrow"
  2696  	case OpcodeSwidenLow:
  2697  		return "SwidenLow"
  2698  	case OpcodeSwidenHigh:
  2699  		return "SwidenHigh"
  2700  	case OpcodeUwidenLow:
  2701  		return "UwidenLow"
  2702  	case OpcodeUwidenHigh:
  2703  		return "UwidenHigh"
  2704  	case OpcodeIaddPairwise:
  2705  		return "IaddPairwise"
  2706  	case OpcodeWideningPairwiseDotProductS:
  2707  		return "WideningPairwiseDotProductS"
  2708  	case OpcodeUExtend:
  2709  		return "UExtend"
  2710  	case OpcodeSExtend:
  2711  		return "SExtend"
  2712  	case OpcodeFpromote:
  2713  		return "Fpromote"
  2714  	case OpcodeFdemote:
  2715  		return "Fdemote"
  2716  	case OpcodeFvdemote:
  2717  		return "Fvdemote"
  2718  	case OpcodeFcvtToUint:
  2719  		return "FcvtToUint"
  2720  	case OpcodeFcvtToSint:
  2721  		return "FcvtToSint"
  2722  	case OpcodeFcvtToUintSat:
  2723  		return "FcvtToUintSat"
  2724  	case OpcodeFcvtToSintSat:
  2725  		return "FcvtToSintSat"
  2726  	case OpcodeFcvtFromUint:
  2727  		return "FcvtFromUint"
  2728  	case OpcodeFcvtFromSint:
  2729  		return "FcvtFromSint"
  2730  	case OpcodeIsplit:
  2731  		return "Isplit"
  2732  	case OpcodeIconcat:
  2733  		return "Iconcat"
  2734  	case OpcodeAtomicRmw:
  2735  		return "AtomicRmw"
  2736  	case OpcodeAtomicCas:
  2737  		return "AtomicCas"
  2738  	case OpcodeAtomicLoad:
  2739  		return "AtomicLoad"
  2740  	case OpcodeAtomicStore:
  2741  		return "AtomicStore"
  2742  	case OpcodeFence:
  2743  		return "Fence"
  2744  	case OpcodeVbor:
  2745  		return "Vbor"
  2746  	case OpcodeVbxor:
  2747  		return "Vbxor"
  2748  	case OpcodeVband:
  2749  		return "Vband"
  2750  	case OpcodeVbandnot:
  2751  		return "Vbandnot"
  2752  	case OpcodeVbnot:
  2753  		return "Vbnot"
  2754  	case OpcodeVbitselect:
  2755  		return "Vbitselect"
  2756  	case OpcodeVIadd:
  2757  		return "VIadd"
  2758  	case OpcodeVSaddSat:
  2759  		return "VSaddSat"
  2760  	case OpcodeVUaddSat:
  2761  		return "VUaddSat"
  2762  	case OpcodeVSsubSat:
  2763  		return "VSsubSat"
  2764  	case OpcodeVUsubSat:
  2765  		return "VUsubSat"
  2766  	case OpcodeVAvgRound:
  2767  		return "OpcodeVAvgRound"
  2768  	case OpcodeVIsub:
  2769  		return "VIsub"
  2770  	case OpcodeVImin:
  2771  		return "VImin"
  2772  	case OpcodeVUmin:
  2773  		return "VUmin"
  2774  	case OpcodeVImax:
  2775  		return "VImax"
  2776  	case OpcodeVUmax:
  2777  		return "VUmax"
  2778  	case OpcodeVImul:
  2779  		return "VImul"
  2780  	case OpcodeVIabs:
  2781  		return "VIabs"
  2782  	case OpcodeVIneg:
  2783  		return "VIneg"
  2784  	case OpcodeVIpopcnt:
  2785  		return "VIpopcnt"
  2786  	case OpcodeVIshl:
  2787  		return "VIshl"
  2788  	case OpcodeVUshr:
  2789  		return "VUshr"
  2790  	case OpcodeVSshr:
  2791  		return "VSshr"
  2792  	case OpcodeVFabs:
  2793  		return "VFabs"
  2794  	case OpcodeVFmax:
  2795  		return "VFmax"
  2796  	case OpcodeVFmin:
  2797  		return "VFmin"
  2798  	case OpcodeVFneg:
  2799  		return "VFneg"
  2800  	case OpcodeVFadd:
  2801  		return "VFadd"
  2802  	case OpcodeVFsub:
  2803  		return "VFsub"
  2804  	case OpcodeVFmul:
  2805  		return "VFmul"
  2806  	case OpcodeVFdiv:
  2807  		return "VFdiv"
  2808  	case OpcodeVFcmp:
  2809  		return "VFcmp"
  2810  	case OpcodeVCeil:
  2811  		return "VCeil"
  2812  	case OpcodeVFloor:
  2813  		return "VFloor"
  2814  	case OpcodeVTrunc:
  2815  		return "VTrunc"
  2816  	case OpcodeVNearest:
  2817  		return "VNearest"
  2818  	case OpcodeVMaxPseudo:
  2819  		return "VMaxPseudo"
  2820  	case OpcodeVMinPseudo:
  2821  		return "VMinPseudo"
  2822  	case OpcodeVSqrt:
  2823  		return "VSqrt"
  2824  	case OpcodeVFcvtToUintSat:
  2825  		return "VFcvtToUintSat"
  2826  	case OpcodeVFcvtToSintSat:
  2827  		return "VFcvtToSintSat"
  2828  	case OpcodeVFcvtFromUint:
  2829  		return "VFcvtFromUint"
  2830  	case OpcodeVFcvtFromSint:
  2831  		return "VFcvtFromSint"
  2832  	case OpcodeFvpromoteLow:
  2833  		return "FvpromoteLow"
  2834  	case OpcodeVZeroExtLoad:
  2835  		return "VZeroExtLoad"
  2836  	}
  2837  	panic(fmt.Sprintf("unknown opcode %d", o))
  2838  }