summaryrefslogtreecommitdiff
path: root/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/instructions.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/instructions.go')
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/instructions.go2976
1 files changed, 0 insertions, 2976 deletions
diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/instructions.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/instructions.go
deleted file mode 100644
index 9a3d1da6e..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/instructions.go
+++ /dev/null
@@ -1,2976 +0,0 @@
-package ssa
-
-import (
- "fmt"
- "math"
- "strings"
-
- "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi"
-)
-
-// Opcode represents a SSA instruction.
-type Opcode uint32
-
-// Instruction represents an instruction whose opcode is specified by
-// Opcode. Since Go doesn't have union type, we use this flattened type
-// for all instructions, and therefore each field has different meaning
-// depending on Opcode.
-type Instruction struct {
- // id is the unique ID of this instruction which ascends from 0 following the order of program.
- id int
- opcode Opcode
- u1, u2 uint64
- v Value
- v2 Value
- v3 Value
- vs Values
- typ Type
- prev, next *Instruction
-
- // rValue is the (first) return value of this instruction.
- // For branching instructions except for OpcodeBrTable, they hold BlockID to jump cast to Value.
- rValue Value
- // rValues are the rest of the return values of this instruction.
- // For OpcodeBrTable, it holds the list of BlockID to jump cast to Value.
- rValues Values
- gid InstructionGroupID
- sourceOffset SourceOffset
- live bool
- alreadyLowered bool
-}
-
-// SourceOffset represents the offset of the source of an instruction.
-type SourceOffset int64
-
-const sourceOffsetUnknown = -1
-
-// Valid returns true if this source offset is valid.
-func (l SourceOffset) Valid() bool {
- return l != sourceOffsetUnknown
-}
-
-func (i *Instruction) annotateSourceOffset(line SourceOffset) {
- i.sourceOffset = line
-}
-
-// SourceOffset returns the source offset of this instruction.
-func (i *Instruction) SourceOffset() SourceOffset {
- return i.sourceOffset
-}
-
-// Opcode returns the opcode of this instruction.
-func (i *Instruction) Opcode() Opcode {
- return i.opcode
-}
-
-// GroupID returns the InstructionGroupID of this instruction.
-func (i *Instruction) GroupID() InstructionGroupID {
- return i.gid
-}
-
-// MarkLowered marks this instruction as already lowered.
-func (i *Instruction) MarkLowered() {
- i.alreadyLowered = true
-}
-
-// Lowered returns true if this instruction is already lowered.
-func (i *Instruction) Lowered() bool {
- return i.alreadyLowered
-}
-
-// resetInstruction resets this instruction to the initial state.
-func resetInstruction(i *Instruction) {
- *i = Instruction{}
- i.v = ValueInvalid
- i.v2 = ValueInvalid
- i.v3 = ValueInvalid
- i.rValue = ValueInvalid
- i.typ = typeInvalid
- i.vs = ValuesNil
- i.sourceOffset = sourceOffsetUnknown
-}
-
-// InstructionGroupID is assigned to each instruction and represents a group of instructions
-// where each instruction is interchangeable with others except for the last instruction
-// in the group which has side effects. In short, InstructionGroupID is determined by the side effects of instructions.
-// That means, if there's an instruction with side effect between two instructions, then these two instructions
-// will have different instructionGroupID. Note that each block always ends with branching, which is with side effects,
-// therefore, instructions in different blocks always have different InstructionGroupID(s).
-//
-// The notable application of this is used in lowering SSA-level instruction to a ISA specific instruction,
-// where we eagerly try to merge multiple instructions into single operation etc. Such merging cannot be done
-// if these instruction have different InstructionGroupID since it will change the semantics of a program.
-//
-// See passDeadCodeElimination.
-type InstructionGroupID uint32
-
-// Returns Value(s) produced by this instruction if any.
-// The `first` is the first return value, and `rest` is the rest of the values.
-func (i *Instruction) Returns() (first Value, rest []Value) {
- if i.IsBranching() {
- return ValueInvalid, nil
- }
- return i.rValue, i.rValues.View()
-}
-
-// Return returns a Value(s) produced by this instruction if any.
-// If there's multiple return values, only the first one is returned.
-func (i *Instruction) Return() (first Value) {
- return i.rValue
-}
-
-// Args returns the arguments to this instruction.
-func (i *Instruction) Args() (v1, v2, v3 Value, vs []Value) {
- return i.v, i.v2, i.v3, i.vs.View()
-}
-
-// Arg returns the first argument to this instruction.
-func (i *Instruction) Arg() Value {
- return i.v
-}
-
-// Arg2 returns the first two arguments to this instruction.
-func (i *Instruction) Arg2() (Value, Value) {
- return i.v, i.v2
-}
-
-// ArgWithLane returns the first argument to this instruction, and the lane type.
-func (i *Instruction) ArgWithLane() (Value, VecLane) {
- return i.v, VecLane(i.u1)
-}
-
-// Arg2WithLane returns the first two arguments to this instruction, and the lane type.
-func (i *Instruction) Arg2WithLane() (Value, Value, VecLane) {
- return i.v, i.v2, VecLane(i.u1)
-}
-
-// ShuffleData returns the first two arguments to this instruction and 2 uint64s `lo`, `hi`.
-//
-// Note: Each uint64 encodes a sequence of 8 bytes where each byte encodes a VecLane,
-// so that the 128bit integer `hi<<64|lo` packs a slice `[16]VecLane`,
-// where `lane[0]` is the least significant byte, and `lane[n]` is shifted to offset `n*8`.
-func (i *Instruction) ShuffleData() (v Value, v2 Value, lo uint64, hi uint64) {
- return i.v, i.v2, i.u1, i.u2
-}
-
-// Arg3 returns the first three arguments to this instruction.
-func (i *Instruction) Arg3() (Value, Value, Value) {
- return i.v, i.v2, i.v3
-}
-
-// Next returns the next instruction laid out next to itself.
-func (i *Instruction) Next() *Instruction {
- return i.next
-}
-
-// Prev returns the previous instruction laid out prior to itself.
-func (i *Instruction) Prev() *Instruction {
- return i.prev
-}
-
-// IsBranching returns true if this instruction is a branching instruction.
-func (i *Instruction) IsBranching() bool {
- switch i.opcode {
- case OpcodeJump, OpcodeBrz, OpcodeBrnz, OpcodeBrTable:
- return true
- default:
- return false
- }
-}
-
-// TODO: complete opcode comments.
-const (
- OpcodeInvalid Opcode = iota
-
- // OpcodeUndefined is a placeholder for undefined opcode. This can be used for debugging to intentionally
- // cause a crash at certain point.
- OpcodeUndefined
-
- // OpcodeJump takes the list of args to the `block` and unconditionally jumps to it.
- OpcodeJump
-
- // OpcodeBrz branches into `blk` with `args` if the value `c` equals zero: `Brz c, blk, args`.
- OpcodeBrz
-
- // OpcodeBrnz branches into `blk` with `args` if the value `c` is not zero: `Brnz c, blk, args`.
- OpcodeBrnz
-
- // OpcodeBrTable takes the index value `index`, and branches into `labelX`. If the `index` is out of range,
- // it branches into the last labelN: `BrTable index, [label1, label2, ... labelN]`.
- OpcodeBrTable
-
- // OpcodeExitWithCode exit the execution immediately.
- OpcodeExitWithCode
-
- // OpcodeExitIfTrueWithCode exits the execution immediately if the value `c` is not zero.
- OpcodeExitIfTrueWithCode
-
- // OpcodeReturn returns from the function: `return rvalues`.
- OpcodeReturn
-
- // OpcodeCall calls a function specified by the symbol FN with arguments `args`: `returnvals = Call FN, args...`
- // This is a "near" call, which means the call target is known at compile time, and the target is relatively close
- // to this function. If the target cannot be reached by near call, the backend fails to compile.
- OpcodeCall
-
- // OpcodeCallIndirect calls a function specified by `callee` which is a function address: `returnvals = call_indirect SIG, callee, args`.
- // Note that this is different from call_indirect in Wasm, which also does type checking, etc.
- OpcodeCallIndirect
-
- // OpcodeSplat performs a vector splat operation: `v = Splat.lane x`.
- OpcodeSplat
-
- // OpcodeSwizzle performs a vector swizzle operation: `v = Swizzle.lane x, y`.
- OpcodeSwizzle
-
- // OpcodeInsertlane inserts a lane value into a vector: `v = InsertLane x, y, Idx`.
- OpcodeInsertlane
-
- // OpcodeExtractlane extracts a lane value from a vector: `v = ExtractLane x, Idx`.
- OpcodeExtractlane
-
- // OpcodeLoad loads a Type value from the [base + offset] address: `v = Load base, offset`.
- OpcodeLoad
-
- // OpcodeStore stores a Type value to the [base + offset] address: `Store v, base, offset`.
- OpcodeStore
-
- // OpcodeUload8 loads the 8-bit value from the [base + offset] address, zero-extended to 64 bits: `v = Uload8 base, offset`.
- OpcodeUload8
-
- // OpcodeSload8 loads the 8-bit value from the [base + offset] address, sign-extended to 64 bits: `v = Sload8 base, offset`.
- OpcodeSload8
-
- // OpcodeIstore8 stores the 8-bit value to the [base + offset] address, sign-extended to 64 bits: `Istore8 v, base, offset`.
- OpcodeIstore8
-
- // OpcodeUload16 loads the 16-bit value from the [base + offset] address, zero-extended to 64 bits: `v = Uload16 base, offset`.
- OpcodeUload16
-
- // OpcodeSload16 loads the 16-bit value from the [base + offset] address, sign-extended to 64 bits: `v = Sload16 base, offset`.
- OpcodeSload16
-
- // OpcodeIstore16 stores the 16-bit value to the [base + offset] address, zero-extended to 64 bits: `Istore16 v, base, offset`.
- OpcodeIstore16
-
- // OpcodeUload32 loads the 32-bit value from the [base + offset] address, zero-extended to 64 bits: `v = Uload32 base, offset`.
- OpcodeUload32
-
- // OpcodeSload32 loads the 32-bit value from the [base + offset] address, sign-extended to 64 bits: `v = Sload32 base, offset`.
- OpcodeSload32
-
- // OpcodeIstore32 stores the 32-bit value to the [base + offset] address, zero-extended to 64 bits: `Istore16 v, base, offset`.
- OpcodeIstore32
-
- // OpcodeLoadSplat represents a load that replicates the loaded value to all lanes `v = LoadSplat.lane p, Offset`.
- OpcodeLoadSplat
-
- // OpcodeVZeroExtLoad loads a scalar single/double precision floating point value from the [p + Offset] address,
- // and zero-extend it to the V128 value: `v = VExtLoad p, Offset`.
- OpcodeVZeroExtLoad
-
- // OpcodeIconst represents the integer const.
- OpcodeIconst
-
- // OpcodeF32const represents the single-precision const.
- OpcodeF32const
-
- // OpcodeF64const represents the double-precision const.
- OpcodeF64const
-
- // OpcodeVconst represents the 128bit vector const.
- OpcodeVconst
-
- // OpcodeVbor computes binary or between two 128bit vectors: `v = bor x, y`.
- OpcodeVbor
-
- // OpcodeVbxor computes binary xor between two 128bit vectors: `v = bxor x, y`.
- OpcodeVbxor
-
- // OpcodeVband computes binary and between two 128bit vectors: `v = band x, y`.
- OpcodeVband
-
- // OpcodeVbandnot computes binary and-not between two 128bit vectors: `v = bandnot x, y`.
- OpcodeVbandnot
-
- // OpcodeVbnot negates a 128bit vector: `v = bnot x`.
- OpcodeVbnot
-
- // OpcodeVbitselect uses the bits in the control mask c to select the corresponding bit from x when 1
- // and y when 0: `v = bitselect c, x, y`.
- OpcodeVbitselect
-
- // OpcodeShuffle shuffles two vectors using the given 128-bit immediate: `v = shuffle imm, x, y`.
- // For each byte in the immediate, a value i in [0, 15] selects the i-th byte in vector x;
- // i in [16, 31] selects the (i-16)-th byte in vector y.
- OpcodeShuffle
-
- // OpcodeSelect chooses between two values based on a condition `c`: `v = Select c, x, y`.
- OpcodeSelect
-
- // OpcodeVanyTrue performs a any true operation: `s = VanyTrue a`.
- OpcodeVanyTrue
-
- // OpcodeVallTrue performs a lane-wise all true operation: `s = VallTrue.lane a`.
- OpcodeVallTrue
-
- // OpcodeVhighBits performs a lane-wise extract of the high bits: `v = VhighBits.lane a`.
- OpcodeVhighBits
-
- // OpcodeIcmp compares two integer values with the given condition: `v = icmp Cond, x, y`.
- OpcodeIcmp
-
- // OpcodeVIcmp compares two integer values with the given condition: `v = vicmp Cond, x, y` on vector.
- OpcodeVIcmp
-
- // OpcodeIcmpImm compares an integer value with the immediate value on the given condition: `v = icmp_imm Cond, x, Y`.
- OpcodeIcmpImm
-
- // OpcodeIadd performs an integer addition: `v = Iadd x, y`.
- OpcodeIadd
-
- // OpcodeVIadd performs an integer addition: `v = VIadd.lane x, y` on vector.
- OpcodeVIadd
-
- // OpcodeVSaddSat performs a signed saturating vector addition: `v = VSaddSat.lane x, y` on vector.
- OpcodeVSaddSat
-
- // OpcodeVUaddSat performs an unsigned saturating vector addition: `v = VUaddSat.lane x, y` on vector.
- OpcodeVUaddSat
-
- // OpcodeIsub performs an integer subtraction: `v = Isub x, y`.
- OpcodeIsub
-
- // OpcodeVIsub performs an integer subtraction: `v = VIsub.lane x, y` on vector.
- OpcodeVIsub
-
- // OpcodeVSsubSat performs a signed saturating vector subtraction: `v = VSsubSat.lane x, y` on vector.
- OpcodeVSsubSat
-
- // OpcodeVUsubSat performs an unsigned saturating vector subtraction: `v = VUsubSat.lane x, y` on vector.
- OpcodeVUsubSat
-
- // OpcodeVImin performs a signed integer min: `v = VImin.lane x, y` on vector.
- OpcodeVImin
-
- // OpcodeVUmin performs an unsigned integer min: `v = VUmin.lane x, y` on vector.
- OpcodeVUmin
-
- // OpcodeVImax performs a signed integer max: `v = VImax.lane x, y` on vector.
- OpcodeVImax
-
- // OpcodeVUmax performs an unsigned integer max: `v = VUmax.lane x, y` on vector.
- OpcodeVUmax
-
- // OpcodeVAvgRound performs an unsigned integer avg, truncating to zero: `v = VAvgRound.lane x, y` on vector.
- OpcodeVAvgRound
-
- // OpcodeVImul performs an integer multiplication: `v = VImul.lane x, y` on vector.
- OpcodeVImul
-
- // OpcodeVIneg negates the given integer vector value: `v = VIneg x`.
- OpcodeVIneg
-
- // OpcodeVIpopcnt counts the number of 1-bits in the given vector: `v = VIpopcnt x`.
- OpcodeVIpopcnt
-
- // OpcodeVIabs returns the absolute value for the given vector value: `v = VIabs.lane x`.
- OpcodeVIabs
-
- // OpcodeVIshl shifts x left by (y mod lane-width): `v = VIshl.lane x, y` on vector.
- OpcodeVIshl
-
- // OpcodeVUshr shifts x right by (y mod lane-width), unsigned: `v = VUshr.lane x, y` on vector.
- OpcodeVUshr
-
- // OpcodeVSshr shifts x right by (y mod lane-width), signed: `v = VSshr.lane x, y` on vector.
- OpcodeVSshr
-
- // OpcodeVFabs takes the absolute value of a floating point value: `v = VFabs.lane x on vector.
- OpcodeVFabs
-
- // OpcodeVFmax takes the maximum of two floating point values: `v = VFmax.lane x, y on vector.
- OpcodeVFmax
-
- // OpcodeVFmin takes the minimum of two floating point values: `v = VFmin.lane x, y on vector.
- OpcodeVFmin
-
- // OpcodeVFneg negates the given floating point vector value: `v = VFneg x`.
- OpcodeVFneg
-
- // OpcodeVFadd performs a floating point addition: `v = VFadd.lane x, y` on vector.
- OpcodeVFadd
-
- // OpcodeVFsub performs a floating point subtraction: `v = VFsub.lane x, y` on vector.
- OpcodeVFsub
-
- // OpcodeVFmul performs a floating point multiplication: `v = VFmul.lane x, y` on vector.
- OpcodeVFmul
-
- // OpcodeVFdiv performs a floating point division: `v = VFdiv.lane x, y` on vector.
- OpcodeVFdiv
-
- // OpcodeVFcmp compares two float values with the given condition: `v = VFcmp.lane Cond, x, y` on float.
- OpcodeVFcmp
-
- // OpcodeVCeil takes the ceiling of the given floating point value: `v = ceil.lane x` on vector.
- OpcodeVCeil
-
- // OpcodeVFloor takes the floor of the given floating point value: `v = floor.lane x` on vector.
- OpcodeVFloor
-
- // OpcodeVTrunc takes the truncation of the given floating point value: `v = trunc.lane x` on vector.
- OpcodeVTrunc
-
- // OpcodeVNearest takes the nearest integer of the given floating point value: `v = nearest.lane x` on vector.
- OpcodeVNearest
-
- // OpcodeVMaxPseudo computes the lane-wise maximum value `v = VMaxPseudo.lane x, y` on vector defined as `x < y ? x : y`.
- OpcodeVMaxPseudo
-
- // OpcodeVMinPseudo computes the lane-wise minimum value `v = VMinPseudo.lane x, y` on vector defined as `y < x ? x : y`.
- OpcodeVMinPseudo
-
- // OpcodeVSqrt takes the minimum of two floating point values: `v = VFmin.lane x, y` on vector.
- OpcodeVSqrt
-
- // OpcodeVFcvtToUintSat converts a floating point value to an unsigned integer: `v = FcvtToUintSat.lane x` on vector.
- OpcodeVFcvtToUintSat
-
- // OpcodeVFcvtToSintSat converts a floating point value to a signed integer: `v = VFcvtToSintSat.lane x` on vector.
- OpcodeVFcvtToSintSat
-
- // OpcodeVFcvtFromUint converts a floating point value from an unsigned integer: `v = FcvtFromUint.lane x` on vector.
- // x is always a 32-bit integer lane, and the result is either a 32-bit or 64-bit floating point-sized vector.
- OpcodeVFcvtFromUint
-
- // OpcodeVFcvtFromSint converts a floating point value from a signed integer: `v = VFcvtFromSint.lane x` on vector.
- // x is always a 32-bit integer lane, and the result is either a 32-bit or 64-bit floating point-sized vector.
- OpcodeVFcvtFromSint
-
- // OpcodeImul performs an integer multiplication: `v = Imul x, y`.
- OpcodeImul
-
- // OpcodeUdiv performs the unsigned integer division `v = Udiv x, y`.
- OpcodeUdiv
-
- // OpcodeSdiv performs the signed integer division `v = Sdiv x, y`.
- OpcodeSdiv
-
- // OpcodeUrem computes the remainder of the unsigned integer division `v = Urem x, y`.
- OpcodeUrem
-
- // OpcodeSrem computes the remainder of the signed integer division `v = Srem x, y`.
- OpcodeSrem
-
- // OpcodeBand performs a binary and: `v = Band x, y`.
- OpcodeBand
-
- // OpcodeBor performs a binary or: `v = Bor x, y`.
- OpcodeBor
-
- // OpcodeBxor performs a binary xor: `v = Bxor x, y`.
- OpcodeBxor
-
- // OpcodeBnot performs a binary not: `v = Bnot x`.
- OpcodeBnot
-
- // OpcodeRotl rotates the given integer value to the left: `v = Rotl x, y`.
- OpcodeRotl
-
- // OpcodeRotr rotates the given integer value to the right: `v = Rotr x, y`.
- OpcodeRotr
-
- // OpcodeIshl does logical shift left: `v = Ishl x, y`.
- OpcodeIshl
-
- // OpcodeUshr does logical shift right: `v = Ushr x, y`.
- OpcodeUshr
-
- // OpcodeSshr does arithmetic shift right: `v = Sshr x, y`.
- OpcodeSshr
-
- // OpcodeClz counts the number of leading zeros: `v = clz x`.
- OpcodeClz
-
- // OpcodeCtz counts the number of trailing zeros: `v = ctz x`.
- OpcodeCtz
-
- // OpcodePopcnt counts the number of 1-bits: `v = popcnt x`.
- OpcodePopcnt
-
- // OpcodeFcmp compares two floating point values: `v = fcmp Cond, x, y`.
- OpcodeFcmp
-
- // OpcodeFadd performs a floating point addition: / `v = Fadd x, y`.
- OpcodeFadd
-
- // OpcodeFsub performs a floating point subtraction: `v = Fsub x, y`.
- OpcodeFsub
-
- // OpcodeFmul performs a floating point multiplication: `v = Fmul x, y`.
- OpcodeFmul
-
- // OpcodeSqmulRoundSat performs a lane-wise saturating rounding multiplication
- // in Q15 format: `v = SqmulRoundSat.lane x,y` on vector.
- OpcodeSqmulRoundSat
-
- // OpcodeFdiv performs a floating point division: `v = Fdiv x, y`.
- OpcodeFdiv
-
- // OpcodeSqrt takes the square root of the given floating point value: `v = sqrt x`.
- OpcodeSqrt
-
- // OpcodeFneg negates the given floating point value: `v = Fneg x`.
- OpcodeFneg
-
- // OpcodeFabs takes the absolute value of the given floating point value: `v = fabs x`.
- OpcodeFabs
-
- // OpcodeFcopysign copies the sign of the second floating point value to the first floating point value:
- // `v = Fcopysign x, y`.
- OpcodeFcopysign
-
- // OpcodeFmin takes the minimum of two floating point values: `v = fmin x, y`.
- OpcodeFmin
-
- // OpcodeFmax takes the maximum of two floating point values: `v = fmax x, y`.
- OpcodeFmax
-
- // OpcodeCeil takes the ceiling of the given floating point value: `v = ceil x`.
- OpcodeCeil
-
- // OpcodeFloor takes the floor of the given floating point value: `v = floor x`.
- OpcodeFloor
-
- // OpcodeTrunc takes the truncation of the given floating point value: `v = trunc x`.
- OpcodeTrunc
-
- // OpcodeNearest takes the nearest integer of the given floating point value: `v = nearest x`.
- OpcodeNearest
-
- // OpcodeBitcast is a bitcast operation: `v = bitcast x`.
- OpcodeBitcast
-
- // OpcodeIreduce narrow the given integer: `v = Ireduce x`.
- OpcodeIreduce
-
- // OpcodeSnarrow converts two input vectors x, y into a smaller lane vector by narrowing each lane, signed `v = Snarrow.lane x, y`.
- OpcodeSnarrow
-
- // OpcodeUnarrow converts two input vectors x, y into a smaller lane vector by narrowing each lane, unsigned `v = Unarrow.lane x, y`.
- OpcodeUnarrow
-
- // OpcodeSwidenLow converts low half of the smaller lane vector to a larger lane vector, sign extended: `v = SwidenLow.lane x`.
- OpcodeSwidenLow
-
- // OpcodeSwidenHigh converts high half of the smaller lane vector to a larger lane vector, sign extended: `v = SwidenHigh.lane x`.
- OpcodeSwidenHigh
-
- // OpcodeUwidenLow converts low half of the smaller lane vector to a larger lane vector, zero (unsigned) extended: `v = UwidenLow.lane x`.
- OpcodeUwidenLow
-
- // OpcodeUwidenHigh converts high half of the smaller lane vector to a larger lane vector, zero (unsigned) extended: `v = UwidenHigh.lane x`.
- OpcodeUwidenHigh
-
- // OpcodeExtIaddPairwise is a lane-wise integer extended pairwise addition producing extended results (twice wider results than the inputs): `v = extiadd_pairwise x, y` on vector.
- OpcodeExtIaddPairwise
-
- // OpcodeWideningPairwiseDotProductS is a lane-wise widening pairwise dot product with signed saturation: `v = WideningPairwiseDotProductS x, y` on vector.
- // Currently, the only lane is i16, and the result is i32.
- OpcodeWideningPairwiseDotProductS
-
- // OpcodeUExtend zero-extends the given integer: `v = UExtend x, from->to`.
- OpcodeUExtend
-
- // OpcodeSExtend sign-extends the given integer: `v = SExtend x, from->to`.
- OpcodeSExtend
-
- // OpcodeFpromote promotes the given floating point value: `v = Fpromote x`.
- OpcodeFpromote
-
- // OpcodeFvpromoteLow converts the two lower single-precision floating point lanes
- // to the two double-precision lanes of the result: `v = FvpromoteLow.lane x` on vector.
- OpcodeFvpromoteLow
-
- // OpcodeFdemote demotes the given float point value: `v = Fdemote x`.
- OpcodeFdemote
-
- // OpcodeFvdemote converts the two double-precision floating point lanes
- // to two lower single-precision lanes of the result `v = Fvdemote.lane x`.
- OpcodeFvdemote
-
- // OpcodeFcvtToUint converts a floating point value to an unsigned integer: `v = FcvtToUint x`.
- OpcodeFcvtToUint
-
- // OpcodeFcvtToSint converts a floating point value to a signed integer: `v = FcvtToSint x`.
- OpcodeFcvtToSint
-
- // OpcodeFcvtToUintSat converts a floating point value to an unsigned integer: `v = FcvtToUintSat x` which saturates on overflow.
- OpcodeFcvtToUintSat
-
- // OpcodeFcvtToSintSat converts a floating point value to a signed integer: `v = FcvtToSintSat x` which saturates on overflow.
- OpcodeFcvtToSintSat
-
- // OpcodeFcvtFromUint converts an unsigned integer to a floating point value: `v = FcvtFromUint x`.
- OpcodeFcvtFromUint
-
- // OpcodeFcvtFromSint converts a signed integer to a floating point value: `v = FcvtFromSint x`.
- OpcodeFcvtFromSint
-
- // OpcodeAtomicRmw is atomic read-modify-write operation: `v = atomic_rmw op, p, offset, value`.
- OpcodeAtomicRmw
-
- // OpcodeAtomicCas is atomic compare-and-swap operation.
- OpcodeAtomicCas
-
- // OpcodeAtomicLoad is atomic load operation.
- OpcodeAtomicLoad
-
- // OpcodeAtomicStore is atomic store operation.
- OpcodeAtomicStore
-
- // OpcodeFence is a memory fence operation.
- OpcodeFence
-
- // opcodeEnd marks the end of the opcode list.
- opcodeEnd
-)
-
-// AtomicRmwOp represents the atomic read-modify-write operation.
-type AtomicRmwOp byte
-
-const (
- // AtomicRmwOpAdd is an atomic add operation.
- AtomicRmwOpAdd AtomicRmwOp = iota
- // AtomicRmwOpSub is an atomic sub operation.
- AtomicRmwOpSub
- // AtomicRmwOpAnd is an atomic and operation.
- AtomicRmwOpAnd
- // AtomicRmwOpOr is an atomic or operation.
- AtomicRmwOpOr
- // AtomicRmwOpXor is an atomic xor operation.
- AtomicRmwOpXor
- // AtomicRmwOpXchg is an atomic swap operation.
- AtomicRmwOpXchg
-)
-
-// String implements the fmt.Stringer.
-func (op AtomicRmwOp) String() string {
- switch op {
- case AtomicRmwOpAdd:
- return "add"
- case AtomicRmwOpSub:
- return "sub"
- case AtomicRmwOpAnd:
- return "and"
- case AtomicRmwOpOr:
- return "or"
- case AtomicRmwOpXor:
- return "xor"
- case AtomicRmwOpXchg:
- return "xchg"
- }
- panic(fmt.Sprintf("unknown AtomicRmwOp: %d", op))
-}
-
-// returnTypesFn provides the info to determine the type of instruction.
-// t1 is the type of the first result, ts are the types of the remaining results.
-type returnTypesFn func(b *builder, instr *Instruction) (t1 Type, ts []Type)
-
-var (
- returnTypesFnNoReturns returnTypesFn = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return typeInvalid, nil }
- returnTypesFnSingle = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return instr.typ, nil }
- returnTypesFnI32 = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return TypeI32, nil }
- returnTypesFnF32 = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return TypeF32, nil }
- returnTypesFnF64 = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return TypeF64, nil }
- returnTypesFnV128 = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return TypeV128, nil }
-)
-
-// sideEffect provides the info to determine if an instruction has side effects which
-// is used to determine if it can be optimized out, interchanged with others, etc.
-type sideEffect byte
-
-const (
- sideEffectUnknown sideEffect = iota
- // sideEffectStrict represents an instruction with side effects, and should be always alive plus cannot be reordered.
- sideEffectStrict
- // sideEffectTraps represents an instruction that can trap, and should be always alive but can be reordered within the group.
- sideEffectTraps
- // sideEffectNone represents an instruction without side effects, and can be eliminated if the result is not used, plus can be reordered within the group.
- sideEffectNone
-)
-
-// instructionSideEffects provides the info to determine if an instruction has side effects.
-// Instructions with side effects must not be eliminated regardless whether the result is used or not.
-var instructionSideEffects = [opcodeEnd]sideEffect{
- OpcodeUndefined: sideEffectStrict,
- OpcodeJump: sideEffectStrict,
- OpcodeIconst: sideEffectNone,
- OpcodeCall: sideEffectStrict,
- OpcodeCallIndirect: sideEffectStrict,
- OpcodeIadd: sideEffectNone,
- OpcodeImul: sideEffectNone,
- OpcodeIsub: sideEffectNone,
- OpcodeIcmp: sideEffectNone,
- OpcodeExtractlane: sideEffectNone,
- OpcodeInsertlane: sideEffectNone,
- OpcodeBand: sideEffectNone,
- OpcodeBor: sideEffectNone,
- OpcodeBxor: sideEffectNone,
- OpcodeRotl: sideEffectNone,
- OpcodeRotr: sideEffectNone,
- OpcodeFcmp: sideEffectNone,
- OpcodeFadd: sideEffectNone,
- OpcodeClz: sideEffectNone,
- OpcodeCtz: sideEffectNone,
- OpcodePopcnt: sideEffectNone,
- OpcodeLoad: sideEffectNone,
- OpcodeLoadSplat: sideEffectNone,
- OpcodeUload8: sideEffectNone,
- OpcodeUload16: sideEffectNone,
- OpcodeUload32: sideEffectNone,
- OpcodeSload8: sideEffectNone,
- OpcodeSload16: sideEffectNone,
- OpcodeSload32: sideEffectNone,
- OpcodeSExtend: sideEffectNone,
- OpcodeUExtend: sideEffectNone,
- OpcodeSwidenLow: sideEffectNone,
- OpcodeUwidenLow: sideEffectNone,
- OpcodeSwidenHigh: sideEffectNone,
- OpcodeUwidenHigh: sideEffectNone,
- OpcodeSnarrow: sideEffectNone,
- OpcodeUnarrow: sideEffectNone,
- OpcodeSwizzle: sideEffectNone,
- OpcodeShuffle: sideEffectNone,
- OpcodeSplat: sideEffectNone,
- OpcodeFsub: sideEffectNone,
- OpcodeF32const: sideEffectNone,
- OpcodeF64const: sideEffectNone,
- OpcodeIshl: sideEffectNone,
- OpcodeSshr: sideEffectNone,
- OpcodeUshr: sideEffectNone,
- OpcodeStore: sideEffectStrict,
- OpcodeIstore8: sideEffectStrict,
- OpcodeIstore16: sideEffectStrict,
- OpcodeIstore32: sideEffectStrict,
- OpcodeExitWithCode: sideEffectStrict,
- OpcodeExitIfTrueWithCode: sideEffectStrict,
- OpcodeReturn: sideEffectStrict,
- OpcodeBrz: sideEffectStrict,
- OpcodeBrnz: sideEffectStrict,
- OpcodeBrTable: sideEffectStrict,
- OpcodeFdiv: sideEffectNone,
- OpcodeFmul: sideEffectNone,
- OpcodeFmax: sideEffectNone,
- OpcodeSqmulRoundSat: sideEffectNone,
- OpcodeSelect: sideEffectNone,
- OpcodeFmin: sideEffectNone,
- OpcodeFneg: sideEffectNone,
- OpcodeFcvtToSint: sideEffectTraps,
- OpcodeFcvtToUint: sideEffectTraps,
- OpcodeFcvtFromSint: sideEffectNone,
- OpcodeFcvtFromUint: sideEffectNone,
- OpcodeFcvtToSintSat: sideEffectNone,
- OpcodeFcvtToUintSat: sideEffectNone,
- OpcodeVFcvtFromUint: sideEffectNone,
- OpcodeVFcvtFromSint: sideEffectNone,
- OpcodeFdemote: sideEffectNone,
- OpcodeFvpromoteLow: sideEffectNone,
- OpcodeFvdemote: sideEffectNone,
- OpcodeFpromote: sideEffectNone,
- OpcodeBitcast: sideEffectNone,
- OpcodeIreduce: sideEffectNone,
- OpcodeSqrt: sideEffectNone,
- OpcodeCeil: sideEffectNone,
- OpcodeFloor: sideEffectNone,
- OpcodeTrunc: sideEffectNone,
- OpcodeNearest: sideEffectNone,
- OpcodeSdiv: sideEffectTraps,
- OpcodeSrem: sideEffectTraps,
- OpcodeUdiv: sideEffectTraps,
- OpcodeUrem: sideEffectTraps,
- OpcodeFabs: sideEffectNone,
- OpcodeFcopysign: sideEffectNone,
- OpcodeExtIaddPairwise: sideEffectNone,
- OpcodeVconst: sideEffectNone,
- OpcodeVbor: sideEffectNone,
- OpcodeVbxor: sideEffectNone,
- OpcodeVband: sideEffectNone,
- OpcodeVbandnot: sideEffectNone,
- OpcodeVbnot: sideEffectNone,
- OpcodeVbitselect: sideEffectNone,
- OpcodeVanyTrue: sideEffectNone,
- OpcodeVallTrue: sideEffectNone,
- OpcodeVhighBits: sideEffectNone,
- OpcodeVIadd: sideEffectNone,
- OpcodeVSaddSat: sideEffectNone,
- OpcodeVUaddSat: sideEffectNone,
- OpcodeVIsub: sideEffectNone,
- OpcodeVSsubSat: sideEffectNone,
- OpcodeVUsubSat: sideEffectNone,
- OpcodeVIcmp: sideEffectNone,
- OpcodeVImin: sideEffectNone,
- OpcodeVUmin: sideEffectNone,
- OpcodeVImax: sideEffectNone,
- OpcodeVUmax: sideEffectNone,
- OpcodeVAvgRound: sideEffectNone,
- OpcodeVImul: sideEffectNone,
- OpcodeVIabs: sideEffectNone,
- OpcodeVIneg: sideEffectNone,
- OpcodeVIpopcnt: sideEffectNone,
- OpcodeVIshl: sideEffectNone,
- OpcodeVSshr: sideEffectNone,
- OpcodeVUshr: sideEffectNone,
- OpcodeVSqrt: sideEffectNone,
- OpcodeVFabs: sideEffectNone,
- OpcodeVFmin: sideEffectNone,
- OpcodeVFmax: sideEffectNone,
- OpcodeVFneg: sideEffectNone,
- OpcodeVFadd: sideEffectNone,
- OpcodeVFsub: sideEffectNone,
- OpcodeVFmul: sideEffectNone,
- OpcodeVFdiv: sideEffectNone,
- OpcodeVFcmp: sideEffectNone,
- OpcodeVCeil: sideEffectNone,
- OpcodeVFloor: sideEffectNone,
- OpcodeVTrunc: sideEffectNone,
- OpcodeVNearest: sideEffectNone,
- OpcodeVMaxPseudo: sideEffectNone,
- OpcodeVMinPseudo: sideEffectNone,
- OpcodeVFcvtToUintSat: sideEffectNone,
- OpcodeVFcvtToSintSat: sideEffectNone,
- OpcodeVZeroExtLoad: sideEffectNone,
- OpcodeAtomicRmw: sideEffectStrict,
- OpcodeAtomicLoad: sideEffectStrict,
- OpcodeAtomicStore: sideEffectStrict,
- OpcodeAtomicCas: sideEffectStrict,
- OpcodeFence: sideEffectStrict,
- OpcodeWideningPairwiseDotProductS: sideEffectNone,
-}
-
-// sideEffect returns true if this instruction has side effects.
-func (i *Instruction) sideEffect() sideEffect {
- if e := instructionSideEffects[i.opcode]; e == sideEffectUnknown {
- panic("BUG: side effect info not registered for " + i.opcode.String())
- } else {
- return e
- }
-}
-
-// instructionReturnTypes provides the function to determine the return types of an instruction.
-var instructionReturnTypes = [opcodeEnd]returnTypesFn{
- OpcodeExtIaddPairwise: returnTypesFnV128,
- OpcodeVbor: returnTypesFnV128,
- OpcodeVbxor: returnTypesFnV128,
- OpcodeVband: returnTypesFnV128,
- OpcodeVbnot: returnTypesFnV128,
- OpcodeVbandnot: returnTypesFnV128,
- OpcodeVbitselect: returnTypesFnV128,
- OpcodeVanyTrue: returnTypesFnI32,
- OpcodeVallTrue: returnTypesFnI32,
- OpcodeVhighBits: returnTypesFnI32,
- OpcodeVIadd: returnTypesFnV128,
- OpcodeVSaddSat: returnTypesFnV128,
- OpcodeVUaddSat: returnTypesFnV128,
- OpcodeVIsub: returnTypesFnV128,
- OpcodeVSsubSat: returnTypesFnV128,
- OpcodeVUsubSat: returnTypesFnV128,
- OpcodeVIcmp: returnTypesFnV128,
- OpcodeVImin: returnTypesFnV128,
- OpcodeVUmin: returnTypesFnV128,
- OpcodeVImax: returnTypesFnV128,
- OpcodeVUmax: returnTypesFnV128,
- OpcodeVImul: returnTypesFnV128,
- OpcodeVAvgRound: returnTypesFnV128,
- OpcodeVIabs: returnTypesFnV128,
- OpcodeVIneg: returnTypesFnV128,
- OpcodeVIpopcnt: returnTypesFnV128,
- OpcodeVIshl: returnTypesFnV128,
- OpcodeVSshr: returnTypesFnV128,
- OpcodeVUshr: returnTypesFnV128,
- OpcodeExtractlane: returnTypesFnSingle,
- OpcodeInsertlane: returnTypesFnV128,
- OpcodeBand: returnTypesFnSingle,
- OpcodeFcopysign: returnTypesFnSingle,
- OpcodeBitcast: returnTypesFnSingle,
- OpcodeBor: returnTypesFnSingle,
- OpcodeBxor: returnTypesFnSingle,
- OpcodeRotl: returnTypesFnSingle,
- OpcodeRotr: returnTypesFnSingle,
- OpcodeIshl: returnTypesFnSingle,
- OpcodeSshr: returnTypesFnSingle,
- OpcodeSdiv: returnTypesFnSingle,
- OpcodeSrem: returnTypesFnSingle,
- OpcodeUdiv: returnTypesFnSingle,
- OpcodeUrem: returnTypesFnSingle,
- OpcodeUshr: returnTypesFnSingle,
- OpcodeJump: returnTypesFnNoReturns,
- OpcodeUndefined: returnTypesFnNoReturns,
- OpcodeIconst: returnTypesFnSingle,
- OpcodeSelect: returnTypesFnSingle,
- OpcodeSExtend: returnTypesFnSingle,
- OpcodeUExtend: returnTypesFnSingle,
- OpcodeSwidenLow: returnTypesFnV128,
- OpcodeUwidenLow: returnTypesFnV128,
- OpcodeSwidenHigh: returnTypesFnV128,
- OpcodeUwidenHigh: returnTypesFnV128,
- OpcodeSnarrow: returnTypesFnV128,
- OpcodeUnarrow: returnTypesFnV128,
- OpcodeSwizzle: returnTypesFnSingle,
- OpcodeShuffle: returnTypesFnV128,
- OpcodeSplat: returnTypesFnV128,
- OpcodeIreduce: returnTypesFnSingle,
- OpcodeFabs: returnTypesFnSingle,
- OpcodeSqrt: returnTypesFnSingle,
- OpcodeCeil: returnTypesFnSingle,
- OpcodeFloor: returnTypesFnSingle,
- OpcodeTrunc: returnTypesFnSingle,
- OpcodeNearest: returnTypesFnSingle,
- OpcodeCallIndirect: func(b *builder, instr *Instruction) (t1 Type, ts []Type) {
- sigID := SignatureID(instr.u1)
- sig, ok := b.signatures[sigID]
- if !ok {
- panic("BUG")
- }
- switch len(sig.Results) {
- case 0:
- t1 = typeInvalid
- case 1:
- t1 = sig.Results[0]
- default:
- t1, ts = sig.Results[0], sig.Results[1:]
- }
- return
- },
- OpcodeCall: func(b *builder, instr *Instruction) (t1 Type, ts []Type) {
- sigID := SignatureID(instr.u2)
- sig, ok := b.signatures[sigID]
- if !ok {
- panic("BUG")
- }
- switch len(sig.Results) {
- case 0:
- t1 = typeInvalid
- case 1:
- t1 = sig.Results[0]
- default:
- t1, ts = sig.Results[0], sig.Results[1:]
- }
- return
- },
- OpcodeLoad: returnTypesFnSingle,
- OpcodeVZeroExtLoad: returnTypesFnV128,
- OpcodeLoadSplat: returnTypesFnV128,
- OpcodeIadd: returnTypesFnSingle,
- OpcodeIsub: returnTypesFnSingle,
- OpcodeImul: returnTypesFnSingle,
- OpcodeIcmp: returnTypesFnI32,
- OpcodeFcmp: returnTypesFnI32,
- OpcodeFadd: returnTypesFnSingle,
- OpcodeFsub: returnTypesFnSingle,
- OpcodeFdiv: returnTypesFnSingle,
- OpcodeFmul: returnTypesFnSingle,
- OpcodeFmax: returnTypesFnSingle,
- OpcodeFmin: returnTypesFnSingle,
- OpcodeSqmulRoundSat: returnTypesFnV128,
- OpcodeF32const: returnTypesFnF32,
- OpcodeF64const: returnTypesFnF64,
- OpcodeClz: returnTypesFnSingle,
- OpcodeCtz: returnTypesFnSingle,
- OpcodePopcnt: returnTypesFnSingle,
- OpcodeStore: returnTypesFnNoReturns,
- OpcodeIstore8: returnTypesFnNoReturns,
- OpcodeIstore16: returnTypesFnNoReturns,
- OpcodeIstore32: returnTypesFnNoReturns,
- OpcodeExitWithCode: returnTypesFnNoReturns,
- OpcodeExitIfTrueWithCode: returnTypesFnNoReturns,
- OpcodeReturn: returnTypesFnNoReturns,
- OpcodeBrz: returnTypesFnNoReturns,
- OpcodeBrnz: returnTypesFnNoReturns,
- OpcodeBrTable: returnTypesFnNoReturns,
- OpcodeUload8: returnTypesFnSingle,
- OpcodeUload16: returnTypesFnSingle,
- OpcodeUload32: returnTypesFnSingle,
- OpcodeSload8: returnTypesFnSingle,
- OpcodeSload16: returnTypesFnSingle,
- OpcodeSload32: returnTypesFnSingle,
- OpcodeFcvtToSint: returnTypesFnSingle,
- OpcodeFcvtToUint: returnTypesFnSingle,
- OpcodeFcvtFromSint: returnTypesFnSingle,
- OpcodeFcvtFromUint: returnTypesFnSingle,
- OpcodeFcvtToSintSat: returnTypesFnSingle,
- OpcodeFcvtToUintSat: returnTypesFnSingle,
- OpcodeVFcvtFromUint: returnTypesFnV128,
- OpcodeVFcvtFromSint: returnTypesFnV128,
- OpcodeFneg: returnTypesFnSingle,
- OpcodeFdemote: returnTypesFnF32,
- OpcodeFvdemote: returnTypesFnV128,
- OpcodeFvpromoteLow: returnTypesFnV128,
- OpcodeFpromote: returnTypesFnF64,
- OpcodeVconst: returnTypesFnV128,
- OpcodeVFabs: returnTypesFnV128,
- OpcodeVSqrt: returnTypesFnV128,
- OpcodeVFmax: returnTypesFnV128,
- OpcodeVFmin: returnTypesFnV128,
- OpcodeVFneg: returnTypesFnV128,
- OpcodeVFadd: returnTypesFnV128,
- OpcodeVFsub: returnTypesFnV128,
- OpcodeVFmul: returnTypesFnV128,
- OpcodeVFdiv: returnTypesFnV128,
- OpcodeVFcmp: returnTypesFnV128,
- OpcodeVCeil: returnTypesFnV128,
- OpcodeVFloor: returnTypesFnV128,
- OpcodeVTrunc: returnTypesFnV128,
- OpcodeVNearest: returnTypesFnV128,
- OpcodeVMaxPseudo: returnTypesFnV128,
- OpcodeVMinPseudo: returnTypesFnV128,
- OpcodeVFcvtToUintSat: returnTypesFnV128,
- OpcodeVFcvtToSintSat: returnTypesFnV128,
- OpcodeAtomicRmw: returnTypesFnSingle,
- OpcodeAtomicLoad: returnTypesFnSingle,
- OpcodeAtomicStore: returnTypesFnNoReturns,
- OpcodeAtomicCas: returnTypesFnSingle,
- OpcodeFence: returnTypesFnNoReturns,
- OpcodeWideningPairwiseDotProductS: returnTypesFnV128,
-}
-
-// AsLoad initializes this instruction as a store instruction with OpcodeLoad.
-func (i *Instruction) AsLoad(ptr Value, offset uint32, typ Type) *Instruction {
- i.opcode = OpcodeLoad
- i.v = ptr
- i.u1 = uint64(offset)
- i.typ = typ
- return i
-}
-
-// AsExtLoad initializes this instruction as a store instruction with OpcodeLoad.
-func (i *Instruction) AsExtLoad(op Opcode, ptr Value, offset uint32, dst64bit bool) *Instruction {
- i.opcode = op
- i.v = ptr
- i.u1 = uint64(offset)
- if dst64bit {
- i.typ = TypeI64
- } else {
- i.typ = TypeI32
- }
- return i
-}
-
-// AsVZeroExtLoad initializes this instruction as a store instruction with OpcodeVExtLoad.
-func (i *Instruction) AsVZeroExtLoad(ptr Value, offset uint32, scalarType Type) *Instruction {
- i.opcode = OpcodeVZeroExtLoad
- i.v = ptr
- i.u1 = uint64(offset)
- i.u2 = uint64(scalarType)
- i.typ = TypeV128
- return i
-}
-
-// VZeroExtLoadData returns the operands for a load instruction. The returned `typ` is the scalar type of the load target.
-func (i *Instruction) VZeroExtLoadData() (ptr Value, offset uint32, typ Type) {
- return i.v, uint32(i.u1), Type(i.u2)
-}
-
-// AsLoadSplat initializes this instruction as a store instruction with OpcodeLoadSplat.
-func (i *Instruction) AsLoadSplat(ptr Value, offset uint32, lane VecLane) *Instruction {
- i.opcode = OpcodeLoadSplat
- i.v = ptr
- i.u1 = uint64(offset)
- i.u2 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// LoadData returns the operands for a load instruction.
-func (i *Instruction) LoadData() (ptr Value, offset uint32, typ Type) {
- return i.v, uint32(i.u1), i.typ
-}
-
-// LoadSplatData returns the operands for a load splat instruction.
-func (i *Instruction) LoadSplatData() (ptr Value, offset uint32, lane VecLane) {
- return i.v, uint32(i.u1), VecLane(i.u2)
-}
-
-// AsStore initializes this instruction as a store instruction with OpcodeStore.
-func (i *Instruction) AsStore(storeOp Opcode, value, ptr Value, offset uint32) *Instruction {
- i.opcode = storeOp
- i.v = value
- i.v2 = ptr
-
- var dstSize uint64
- switch storeOp {
- case OpcodeStore:
- dstSize = uint64(value.Type().Bits())
- case OpcodeIstore8:
- dstSize = 8
- case OpcodeIstore16:
- dstSize = 16
- case OpcodeIstore32:
- dstSize = 32
- default:
- panic("invalid store opcode" + storeOp.String())
- }
- i.u1 = uint64(offset) | dstSize<<32
- return i
-}
-
-// StoreData returns the operands for a store instruction.
-func (i *Instruction) StoreData() (value, ptr Value, offset uint32, storeSizeInBits byte) {
- return i.v, i.v2, uint32(i.u1), byte(i.u1 >> 32)
-}
-
-// AsIconst64 initializes this instruction as a 64-bit integer constant instruction with OpcodeIconst.
-func (i *Instruction) AsIconst64(v uint64) *Instruction {
- i.opcode = OpcodeIconst
- i.typ = TypeI64
- i.u1 = v
- return i
-}
-
-// AsIconst32 initializes this instruction as a 32-bit integer constant instruction with OpcodeIconst.
-func (i *Instruction) AsIconst32(v uint32) *Instruction {
- i.opcode = OpcodeIconst
- i.typ = TypeI32
- i.u1 = uint64(v)
- return i
-}
-
-// AsIadd initializes this instruction as an integer addition instruction with OpcodeIadd.
-func (i *Instruction) AsIadd(x, y Value) *Instruction {
- i.opcode = OpcodeIadd
- i.v = x
- i.v2 = y
- i.typ = x.Type()
- return i
-}
-
-// AsVIadd initializes this instruction as an integer addition instruction with OpcodeVIadd on a vector.
-func (i *Instruction) AsVIadd(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVIadd
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsWideningPairwiseDotProductS initializes this instruction as a lane-wise integer extended pairwise addition instruction
-// with OpcodeIaddPairwise on a vector.
-func (i *Instruction) AsWideningPairwiseDotProductS(x, y Value) *Instruction {
- i.opcode = OpcodeWideningPairwiseDotProductS
- i.v = x
- i.v2 = y
- i.typ = TypeV128
- return i
-}
-
-// AsExtIaddPairwise initializes this instruction as a lane-wise integer extended pairwise addition instruction
-// with OpcodeIaddPairwise on a vector.
-func (i *Instruction) AsExtIaddPairwise(x Value, srcLane VecLane, signed bool) *Instruction {
- i.opcode = OpcodeExtIaddPairwise
- i.v = x
- i.u1 = uint64(srcLane)
- if signed {
- i.u2 = 1
- }
- i.typ = TypeV128
- return i
-}
-
-// ExtIaddPairwiseData returns the operands for a lane-wise integer extended pairwise addition instruction.
-func (i *Instruction) ExtIaddPairwiseData() (x Value, srcLane VecLane, signed bool) {
- return i.v, VecLane(i.u1), i.u2 != 0
-}
-
-// AsVSaddSat initializes this instruction as a vector addition with saturation instruction with OpcodeVSaddSat on a vector.
-func (i *Instruction) AsVSaddSat(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVSaddSat
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVUaddSat initializes this instruction as a vector addition with saturation instruction with OpcodeVUaddSat on a vector.
-func (i *Instruction) AsVUaddSat(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVUaddSat
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVIsub initializes this instruction as an integer subtraction instruction with OpcodeVIsub on a vector.
-func (i *Instruction) AsVIsub(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVIsub
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVSsubSat initializes this instruction as a vector addition with saturation instruction with OpcodeVSsubSat on a vector.
-func (i *Instruction) AsVSsubSat(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVSsubSat
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVUsubSat initializes this instruction as a vector addition with saturation instruction with OpcodeVUsubSat on a vector.
-func (i *Instruction) AsVUsubSat(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVUsubSat
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVImin initializes this instruction as a signed integer min instruction with OpcodeVImin on a vector.
-func (i *Instruction) AsVImin(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVImin
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVUmin initializes this instruction as an unsigned integer min instruction with OpcodeVUmin on a vector.
-func (i *Instruction) AsVUmin(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVUmin
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVImax initializes this instruction as a signed integer max instruction with OpcodeVImax on a vector.
-func (i *Instruction) AsVImax(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVImax
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVUmax initializes this instruction as an unsigned integer max instruction with OpcodeVUmax on a vector.
-func (i *Instruction) AsVUmax(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVUmax
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVAvgRound initializes this instruction as an unsigned integer avg instruction, truncating to zero with OpcodeVAvgRound on a vector.
-func (i *Instruction) AsVAvgRound(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVAvgRound
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVImul initializes this instruction as an integer multiplication with OpcodeVImul on a vector.
-func (i *Instruction) AsVImul(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVImul
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsSqmulRoundSat initializes this instruction as a lane-wise saturating rounding multiplication
-// in Q15 format with OpcodeSqmulRoundSat on a vector.
-func (i *Instruction) AsSqmulRoundSat(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeSqmulRoundSat
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVIabs initializes this instruction as a vector absolute value with OpcodeVIabs.
-func (i *Instruction) AsVIabs(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVIabs
- i.v = x
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVIneg initializes this instruction as a vector negation with OpcodeVIneg.
-func (i *Instruction) AsVIneg(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVIneg
- i.v = x
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVIpopcnt initializes this instruction as a Population Count instruction with OpcodeVIpopcnt on a vector.
-func (i *Instruction) AsVIpopcnt(x Value, lane VecLane) *Instruction {
- if lane != VecLaneI8x16 {
- panic("Unsupported lane type " + lane.String())
- }
- i.opcode = OpcodeVIpopcnt
- i.v = x
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVSqrt initializes this instruction as a sqrt instruction with OpcodeVSqrt on a vector.
-func (i *Instruction) AsVSqrt(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVSqrt
- i.v = x
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVFabs initializes this instruction as a float abs instruction with OpcodeVFabs on a vector.
-func (i *Instruction) AsVFabs(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVFabs
- i.v = x
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVFneg initializes this instruction as a float neg instruction with OpcodeVFneg on a vector.
-func (i *Instruction) AsVFneg(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVFneg
- i.v = x
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVFmax initializes this instruction as a float max instruction with OpcodeVFmax on a vector.
-func (i *Instruction) AsVFmax(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVFmax
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVFmin initializes this instruction as a float min instruction with OpcodeVFmin on a vector.
-func (i *Instruction) AsVFmin(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVFmin
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVFadd initializes this instruction as a floating point add instruction with OpcodeVFadd on a vector.
-func (i *Instruction) AsVFadd(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVFadd
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVFsub initializes this instruction as a floating point subtraction instruction with OpcodeVFsub on a vector.
-func (i *Instruction) AsVFsub(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVFsub
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVFmul initializes this instruction as a floating point multiplication instruction with OpcodeVFmul on a vector.
-func (i *Instruction) AsVFmul(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVFmul
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVFdiv initializes this instruction as a floating point division instruction with OpcodeVFdiv on a vector.
-func (i *Instruction) AsVFdiv(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVFdiv
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsImul initializes this instruction as an integer addition instruction with OpcodeImul.
-func (i *Instruction) AsImul(x, y Value) *Instruction {
- i.opcode = OpcodeImul
- i.v = x
- i.v2 = y
- i.typ = x.Type()
- return i
-}
-
-func (i *Instruction) Insert(b Builder) *Instruction {
- b.InsertInstruction(i)
- return i
-}
-
-// AsIsub initializes this instruction as an integer subtraction instruction with OpcodeIsub.
-func (i *Instruction) AsIsub(x, y Value) *Instruction {
- i.opcode = OpcodeIsub
- i.v = x
- i.v2 = y
- i.typ = x.Type()
- return i
-}
-
-// AsIcmp initializes this instruction as an integer comparison instruction with OpcodeIcmp.
-func (i *Instruction) AsIcmp(x, y Value, c IntegerCmpCond) *Instruction {
- i.opcode = OpcodeIcmp
- i.v = x
- i.v2 = y
- i.u1 = uint64(c)
- i.typ = TypeI32
- return i
-}
-
-// AsFcmp initializes this instruction as an integer comparison instruction with OpcodeFcmp.
-func (i *Instruction) AsFcmp(x, y Value, c FloatCmpCond) {
- i.opcode = OpcodeFcmp
- i.v = x
- i.v2 = y
- i.u1 = uint64(c)
- i.typ = TypeI32
-}
-
-// AsVIcmp initializes this instruction as an integer vector comparison instruction with OpcodeVIcmp.
-func (i *Instruction) AsVIcmp(x, y Value, c IntegerCmpCond, lane VecLane) *Instruction {
- i.opcode = OpcodeVIcmp
- i.v = x
- i.v2 = y
- i.u1 = uint64(c)
- i.u2 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsVFcmp initializes this instruction as a float comparison instruction with OpcodeVFcmp on Vector.
-func (i *Instruction) AsVFcmp(x, y Value, c FloatCmpCond, lane VecLane) *Instruction {
- i.opcode = OpcodeVFcmp
- i.v = x
- i.v2 = y
- i.u1 = uint64(c)
- i.typ = TypeV128
- i.u2 = uint64(lane)
- return i
-}
-
-// AsVCeil initializes this instruction as an instruction with OpcodeCeil.
-func (i *Instruction) AsVCeil(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVCeil
- i.v = x
- i.typ = x.Type()
- i.u1 = uint64(lane)
- return i
-}
-
-// AsVFloor initializes this instruction as an instruction with OpcodeFloor.
-func (i *Instruction) AsVFloor(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVFloor
- i.v = x
- i.typ = x.Type()
- i.u1 = uint64(lane)
- return i
-}
-
-// AsVTrunc initializes this instruction as an instruction with OpcodeTrunc.
-func (i *Instruction) AsVTrunc(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVTrunc
- i.v = x
- i.typ = x.Type()
- i.u1 = uint64(lane)
- return i
-}
-
-// AsVNearest initializes this instruction as an instruction with OpcodeNearest.
-func (i *Instruction) AsVNearest(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVNearest
- i.v = x
- i.typ = x.Type()
- i.u1 = uint64(lane)
- return i
-}
-
-// AsVMaxPseudo initializes this instruction as an instruction with OpcodeVMaxPseudo.
-func (i *Instruction) AsVMaxPseudo(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVMaxPseudo
- i.typ = x.Type()
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- return i
-}
-
-// AsVMinPseudo initializes this instruction as an instruction with OpcodeVMinPseudo.
-func (i *Instruction) AsVMinPseudo(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVMinPseudo
- i.typ = x.Type()
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- return i
-}
-
-// AsSDiv initializes this instruction as an integer bitwise and instruction with OpcodeSdiv.
-func (i *Instruction) AsSDiv(x, y, ctx Value) *Instruction {
- i.opcode = OpcodeSdiv
- i.v = x
- i.v2 = y
- i.v3 = ctx
- i.typ = x.Type()
- return i
-}
-
-// AsUDiv initializes this instruction as an integer bitwise and instruction with OpcodeUdiv.
-func (i *Instruction) AsUDiv(x, y, ctx Value) *Instruction {
- i.opcode = OpcodeUdiv
- i.v = x
- i.v2 = y
- i.v3 = ctx
- i.typ = x.Type()
- return i
-}
-
-// AsSRem initializes this instruction as an integer bitwise and instruction with OpcodeSrem.
-func (i *Instruction) AsSRem(x, y, ctx Value) *Instruction {
- i.opcode = OpcodeSrem
- i.v = x
- i.v2 = y
- i.v3 = ctx
- i.typ = x.Type()
- return i
-}
-
-// AsURem initializes this instruction as an integer bitwise and instruction with OpcodeUrem.
-func (i *Instruction) AsURem(x, y, ctx Value) *Instruction {
- i.opcode = OpcodeUrem
- i.v = x
- i.v2 = y
- i.v3 = ctx
- i.typ = x.Type()
- return i
-}
-
-// AsBand initializes this instruction as an integer bitwise and instruction with OpcodeBand.
-func (i *Instruction) AsBand(x, amount Value) *Instruction {
- i.opcode = OpcodeBand
- i.v = x
- i.v2 = amount
- i.typ = x.Type()
- return i
-}
-
-// AsBor initializes this instruction as an integer bitwise or instruction with OpcodeBor.
-func (i *Instruction) AsBor(x, amount Value) {
- i.opcode = OpcodeBor
- i.v = x
- i.v2 = amount
- i.typ = x.Type()
-}
-
-// AsBxor initializes this instruction as an integer bitwise xor instruction with OpcodeBxor.
-func (i *Instruction) AsBxor(x, amount Value) {
- i.opcode = OpcodeBxor
- i.v = x
- i.v2 = amount
- i.typ = x.Type()
-}
-
-// AsIshl initializes this instruction as an integer shift left instruction with OpcodeIshl.
-func (i *Instruction) AsIshl(x, amount Value) *Instruction {
- i.opcode = OpcodeIshl
- i.v = x
- i.v2 = amount
- i.typ = x.Type()
- return i
-}
-
-// AsVIshl initializes this instruction as an integer shift left instruction with OpcodeVIshl on vector.
-func (i *Instruction) AsVIshl(x, amount Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVIshl
- i.v = x
- i.v2 = amount
- i.u1 = uint64(lane)
- i.typ = x.Type()
- return i
-}
-
-// AsUshr initializes this instruction as an integer unsigned shift right (logical shift right) instruction with OpcodeUshr.
-func (i *Instruction) AsUshr(x, amount Value) *Instruction {
- i.opcode = OpcodeUshr
- i.v = x
- i.v2 = amount
- i.typ = x.Type()
- return i
-}
-
-// AsVUshr initializes this instruction as an integer unsigned shift right (logical shift right) instruction with OpcodeVUshr on vector.
-func (i *Instruction) AsVUshr(x, amount Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVUshr
- i.v = x
- i.v2 = amount
- i.u1 = uint64(lane)
- i.typ = x.Type()
- return i
-}
-
-// AsSshr initializes this instruction as an integer signed shift right (arithmetic shift right) instruction with OpcodeSshr.
-func (i *Instruction) AsSshr(x, amount Value) *Instruction {
- i.opcode = OpcodeSshr
- i.v = x
- i.v2 = amount
- i.typ = x.Type()
- return i
-}
-
-// AsVSshr initializes this instruction as an integer signed shift right (arithmetic shift right) instruction with OpcodeVSshr on vector.
-func (i *Instruction) AsVSshr(x, amount Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVSshr
- i.v = x
- i.v2 = amount
- i.u1 = uint64(lane)
- i.typ = x.Type()
- return i
-}
-
-// AsExtractlane initializes this instruction as an extract lane instruction with OpcodeExtractlane on vector.
-func (i *Instruction) AsExtractlane(x Value, index byte, lane VecLane, signed bool) *Instruction {
- i.opcode = OpcodeExtractlane
- i.v = x
- // We do not have a field for signedness, but `index` is a byte,
- // so we just encode the flag in the high bits of `u1`.
- i.u1 = uint64(index)
- if signed {
- i.u1 = i.u1 | 1<<32
- }
- i.u2 = uint64(lane)
- switch lane {
- case VecLaneI8x16, VecLaneI16x8, VecLaneI32x4:
- i.typ = TypeI32
- case VecLaneI64x2:
- i.typ = TypeI64
- case VecLaneF32x4:
- i.typ = TypeF32
- case VecLaneF64x2:
- i.typ = TypeF64
- }
- return i
-}
-
-// AsInsertlane initializes this instruction as an insert lane instruction with OpcodeInsertlane on vector.
-func (i *Instruction) AsInsertlane(x, y Value, index byte, lane VecLane) *Instruction {
- i.opcode = OpcodeInsertlane
- i.v = x
- i.v2 = y
- i.u1 = uint64(index)
- i.u2 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsShuffle initializes this instruction as a shuffle instruction with OpcodeShuffle on vector.
-func (i *Instruction) AsShuffle(x, y Value, lane []byte) *Instruction {
- i.opcode = OpcodeShuffle
- i.v = x
- i.v2 = y
- // Encode the 16 bytes as 8 bytes in u1, and 8 bytes in u2.
- 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])
- 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])
- i.typ = TypeV128
- return i
-}
-
-// AsSwizzle initializes this instruction as an insert lane instruction with OpcodeSwizzle on vector.
-func (i *Instruction) AsSwizzle(x, y Value, lane VecLane) *Instruction {
- i.opcode = OpcodeSwizzle
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsSplat initializes this instruction as an insert lane instruction with OpcodeSplat on vector.
-func (i *Instruction) AsSplat(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeSplat
- i.v = x
- i.u1 = uint64(lane)
- i.typ = TypeV128
- return i
-}
-
-// AsRotl initializes this instruction as a word rotate left instruction with OpcodeRotl.
-func (i *Instruction) AsRotl(x, amount Value) {
- i.opcode = OpcodeRotl
- i.v = x
- i.v2 = amount
- i.typ = x.Type()
-}
-
-// AsRotr initializes this instruction as a word rotate right instruction with OpcodeRotr.
-func (i *Instruction) AsRotr(x, amount Value) {
- i.opcode = OpcodeRotr
- i.v = x
- i.v2 = amount
- i.typ = x.Type()
-}
-
-// IcmpData returns the operands and comparison condition of this integer comparison instruction.
-func (i *Instruction) IcmpData() (x, y Value, c IntegerCmpCond) {
- return i.v, i.v2, IntegerCmpCond(i.u1)
-}
-
-// FcmpData returns the operands and comparison condition of this floating-point comparison instruction.
-func (i *Instruction) FcmpData() (x, y Value, c FloatCmpCond) {
- return i.v, i.v2, FloatCmpCond(i.u1)
-}
-
-// VIcmpData returns the operands and comparison condition of this integer comparison instruction on vector.
-func (i *Instruction) VIcmpData() (x, y Value, c IntegerCmpCond, l VecLane) {
- return i.v, i.v2, IntegerCmpCond(i.u1), VecLane(i.u2)
-}
-
-// VFcmpData returns the operands and comparison condition of this float comparison instruction on vector.
-func (i *Instruction) VFcmpData() (x, y Value, c FloatCmpCond, l VecLane) {
- return i.v, i.v2, FloatCmpCond(i.u1), VecLane(i.u2)
-}
-
-// ExtractlaneData returns the operands and sign flag of Extractlane on vector.
-func (i *Instruction) ExtractlaneData() (x Value, index byte, signed bool, l VecLane) {
- x = i.v
- index = byte(0b00001111 & i.u1)
- signed = i.u1>>32 != 0
- l = VecLane(i.u2)
- return
-}
-
-// InsertlaneData returns the operands and sign flag of Insertlane on vector.
-func (i *Instruction) InsertlaneData() (x, y Value, index byte, l VecLane) {
- x = i.v
- y = i.v2
- index = byte(i.u1)
- l = VecLane(i.u2)
- return
-}
-
-// AsFadd initializes this instruction as a floating-point addition instruction with OpcodeFadd.
-func (i *Instruction) AsFadd(x, y Value) {
- i.opcode = OpcodeFadd
- i.v = x
- i.v2 = y
- i.typ = x.Type()
-}
-
-// AsFsub initializes this instruction as a floating-point subtraction instruction with OpcodeFsub.
-func (i *Instruction) AsFsub(x, y Value) {
- i.opcode = OpcodeFsub
- i.v = x
- i.v2 = y
- i.typ = x.Type()
-}
-
-// AsFmul initializes this instruction as a floating-point multiplication instruction with OpcodeFmul.
-func (i *Instruction) AsFmul(x, y Value) {
- i.opcode = OpcodeFmul
- i.v = x
- i.v2 = y
- i.typ = x.Type()
-}
-
-// AsFdiv initializes this instruction as a floating-point division instruction with OpcodeFdiv.
-func (i *Instruction) AsFdiv(x, y Value) {
- i.opcode = OpcodeFdiv
- i.v = x
- i.v2 = y
- i.typ = x.Type()
-}
-
-// AsFmin initializes this instruction to take the minimum of two floating-points with OpcodeFmin.
-func (i *Instruction) AsFmin(x, y Value) {
- i.opcode = OpcodeFmin
- i.v = x
- i.v2 = y
- i.typ = x.Type()
-}
-
-// AsFmax initializes this instruction to take the maximum of two floating-points with OpcodeFmax.
-func (i *Instruction) AsFmax(x, y Value) {
- i.opcode = OpcodeFmax
- i.v = x
- i.v2 = y
- i.typ = x.Type()
-}
-
-// AsF32const initializes this instruction as a 32-bit floating-point constant instruction with OpcodeF32const.
-func (i *Instruction) AsF32const(f float32) *Instruction {
- i.opcode = OpcodeF32const
- i.typ = TypeF64
- i.u1 = uint64(math.Float32bits(f))
- return i
-}
-
-// AsF64const initializes this instruction as a 64-bit floating-point constant instruction with OpcodeF64const.
-func (i *Instruction) AsF64const(f float64) *Instruction {
- i.opcode = OpcodeF64const
- i.typ = TypeF64
- i.u1 = math.Float64bits(f)
- return i
-}
-
-// AsVconst initializes this instruction as a vector constant instruction with OpcodeVconst.
-func (i *Instruction) AsVconst(lo, hi uint64) *Instruction {
- i.opcode = OpcodeVconst
- i.typ = TypeV128
- i.u1 = lo
- i.u2 = hi
- return i
-}
-
-// AsVbnot initializes this instruction as a vector negation instruction with OpcodeVbnot.
-func (i *Instruction) AsVbnot(v Value) *Instruction {
- i.opcode = OpcodeVbnot
- i.typ = TypeV128
- i.v = v
- return i
-}
-
-// AsVband initializes this instruction as an and vector instruction with OpcodeVband.
-func (i *Instruction) AsVband(x, y Value) *Instruction {
- i.opcode = OpcodeVband
- i.typ = TypeV128
- i.v = x
- i.v2 = y
- return i
-}
-
-// AsVbor initializes this instruction as an or vector instruction with OpcodeVbor.
-func (i *Instruction) AsVbor(x, y Value) *Instruction {
- i.opcode = OpcodeVbor
- i.typ = TypeV128
- i.v = x
- i.v2 = y
- return i
-}
-
-// AsVbxor initializes this instruction as a xor vector instruction with OpcodeVbxor.
-func (i *Instruction) AsVbxor(x, y Value) *Instruction {
- i.opcode = OpcodeVbxor
- i.typ = TypeV128
- i.v = x
- i.v2 = y
- return i
-}
-
-// AsVbandnot initializes this instruction as an and-not vector instruction with OpcodeVbandnot.
-func (i *Instruction) AsVbandnot(x, y Value) *Instruction {
- i.opcode = OpcodeVbandnot
- i.typ = TypeV128
- i.v = x
- i.v2 = y
- return i
-}
-
-// AsVbitselect initializes this instruction as a bit select vector instruction with OpcodeVbitselect.
-func (i *Instruction) AsVbitselect(c, x, y Value) *Instruction {
- i.opcode = OpcodeVbitselect
- i.typ = TypeV128
- i.v = c
- i.v2 = x
- i.v3 = y
- return i
-}
-
-// AsVanyTrue initializes this instruction as an anyTrue vector instruction with OpcodeVanyTrue.
-func (i *Instruction) AsVanyTrue(x Value) *Instruction {
- i.opcode = OpcodeVanyTrue
- i.typ = TypeI32
- i.v = x
- return i
-}
-
-// AsVallTrue initializes this instruction as an allTrue vector instruction with OpcodeVallTrue.
-func (i *Instruction) AsVallTrue(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVallTrue
- i.typ = TypeI32
- i.v = x
- i.u1 = uint64(lane)
- return i
-}
-
-// AsVhighBits initializes this instruction as a highBits vector instruction with OpcodeVhighBits.
-func (i *Instruction) AsVhighBits(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeVhighBits
- i.typ = TypeI32
- i.v = x
- i.u1 = uint64(lane)
- return i
-}
-
-// VconstData returns the operands of this vector constant instruction.
-func (i *Instruction) VconstData() (lo, hi uint64) {
- return i.u1, i.u2
-}
-
-// AsReturn initializes this instruction as a return instruction with OpcodeReturn.
-func (i *Instruction) AsReturn(vs wazevoapi.VarLength[Value]) *Instruction {
- i.opcode = OpcodeReturn
- i.vs = vs
- return i
-}
-
-// AsIreduce initializes this instruction as a reduction instruction with OpcodeIreduce.
-func (i *Instruction) AsIreduce(v Value, dstType Type) *Instruction {
- i.opcode = OpcodeIreduce
- i.v = v
- i.typ = dstType
- return i
-}
-
-// AsWiden initializes this instruction as a signed or unsigned widen instruction
-// on low half or high half of the given vector with OpcodeSwidenLow, OpcodeUwidenLow, OpcodeSwidenHigh, OpcodeUwidenHigh.
-func (i *Instruction) AsWiden(v Value, lane VecLane, signed, low bool) *Instruction {
- switch {
- case signed && low:
- i.opcode = OpcodeSwidenLow
- case !signed && low:
- i.opcode = OpcodeUwidenLow
- case signed && !low:
- i.opcode = OpcodeSwidenHigh
- case !signed && !low:
- i.opcode = OpcodeUwidenHigh
- }
- i.v = v
- i.u1 = uint64(lane)
- return i
-}
-
-// AsAtomicLoad initializes this instruction as an atomic load.
-// The size is in bytes and must be 1, 2, 4, or 8.
-func (i *Instruction) AsAtomicLoad(addr Value, size uint64, typ Type) *Instruction {
- i.opcode = OpcodeAtomicLoad
- i.u1 = size
- i.v = addr
- i.typ = typ
- return i
-}
-
-// AsAtomicLoad initializes this instruction as an atomic store.
-// The size is in bytes and must be 1, 2, 4, or 8.
-func (i *Instruction) AsAtomicStore(addr, val Value, size uint64) *Instruction {
- i.opcode = OpcodeAtomicStore
- i.u1 = size
- i.v = addr
- i.v2 = val
- i.typ = val.Type()
- return i
-}
-
-// AsAtomicRmw initializes this instruction as an atomic read-modify-write.
-// The size is in bytes and must be 1, 2, 4, or 8.
-func (i *Instruction) AsAtomicRmw(op AtomicRmwOp, addr, val Value, size uint64) *Instruction {
- i.opcode = OpcodeAtomicRmw
- i.u1 = uint64(op)
- i.u2 = size
- i.v = addr
- i.v2 = val
- i.typ = val.Type()
- return i
-}
-
-// AsAtomicCas initializes this instruction as an atomic compare-and-swap.
-// The size is in bytes and must be 1, 2, 4, or 8.
-func (i *Instruction) AsAtomicCas(addr, exp, repl Value, size uint64) *Instruction {
- i.opcode = OpcodeAtomicCas
- i.u1 = size
- i.v = addr
- i.v2 = exp
- i.v3 = repl
- i.typ = repl.Type()
- return i
-}
-
-// AsFence initializes this instruction as a memory fence.
-// A single byte immediate may be used to indicate fence ordering in the future
-// but is currently always 0 and ignored.
-func (i *Instruction) AsFence(order byte) *Instruction {
- i.opcode = OpcodeFence
- i.u1 = uint64(order)
- return i
-}
-
-// AtomicRmwData returns the data for this atomic read-modify-write instruction.
-func (i *Instruction) AtomicRmwData() (op AtomicRmwOp, size uint64) {
- return AtomicRmwOp(i.u1), i.u2
-}
-
-// AtomicTargetSize returns the target memory size of the atomic instruction.
-func (i *Instruction) AtomicTargetSize() (size uint64) {
- return i.u1
-}
-
-// ReturnVals returns the return values of OpcodeReturn.
-func (i *Instruction) ReturnVals() []Value {
- return i.vs.View()
-}
-
-// AsExitWithCode initializes this instruction as a trap instruction with OpcodeExitWithCode.
-func (i *Instruction) AsExitWithCode(ctx Value, code wazevoapi.ExitCode) {
- i.opcode = OpcodeExitWithCode
- i.v = ctx
- i.u1 = uint64(code)
-}
-
-// AsExitIfTrueWithCode initializes this instruction as a trap instruction with OpcodeExitIfTrueWithCode.
-func (i *Instruction) AsExitIfTrueWithCode(ctx, c Value, code wazevoapi.ExitCode) *Instruction {
- i.opcode = OpcodeExitIfTrueWithCode
- i.v = ctx
- i.v2 = c
- i.u1 = uint64(code)
- return i
-}
-
-// ExitWithCodeData returns the context and exit code of OpcodeExitWithCode.
-func (i *Instruction) ExitWithCodeData() (ctx Value, code wazevoapi.ExitCode) {
- return i.v, wazevoapi.ExitCode(i.u1)
-}
-
-// ExitIfTrueWithCodeData returns the context and exit code of OpcodeExitWithCode.
-func (i *Instruction) ExitIfTrueWithCodeData() (ctx, c Value, code wazevoapi.ExitCode) {
- return i.v, i.v2, wazevoapi.ExitCode(i.u1)
-}
-
-// InvertBrx inverts either OpcodeBrz or OpcodeBrnz to the other.
-func (i *Instruction) InvertBrx() {
- switch i.opcode {
- case OpcodeBrz:
- i.opcode = OpcodeBrnz
- case OpcodeBrnz:
- i.opcode = OpcodeBrz
- default:
- panic("BUG")
- }
-}
-
-// BranchData returns the branch data for this instruction necessary for backends.
-func (i *Instruction) BranchData() (condVal Value, blockArgs []Value, target BasicBlockID) {
- switch i.opcode {
- case OpcodeJump:
- condVal = ValueInvalid
- case OpcodeBrz, OpcodeBrnz:
- condVal = i.v
- default:
- panic("BUG")
- }
- blockArgs = i.vs.View()
- target = BasicBlockID(i.rValue)
- return
-}
-
-// BrTableData returns the branch table data for this instruction necessary for backends.
-func (i *Instruction) BrTableData() (index Value, targets Values) {
- if i.opcode != OpcodeBrTable {
- panic("BUG: BrTableData only available for OpcodeBrTable")
- }
- index = i.v
- targets = i.rValues
- return
-}
-
-// AsJump initializes this instruction as a jump instruction with OpcodeJump.
-func (i *Instruction) AsJump(vs Values, target BasicBlock) *Instruction {
- i.opcode = OpcodeJump
- i.vs = vs
- i.rValue = Value(target.ID())
- return i
-}
-
-// IsFallthroughJump returns true if this instruction is a fallthrough jump.
-func (i *Instruction) IsFallthroughJump() bool {
- if i.opcode != OpcodeJump {
- panic("BUG: IsFallthrough only available for OpcodeJump")
- }
- return i.opcode == OpcodeJump && i.u1 != 0
-}
-
-// AsFallthroughJump marks this instruction as a fallthrough jump.
-func (i *Instruction) AsFallthroughJump() {
- if i.opcode != OpcodeJump {
- panic("BUG: AsFallthroughJump only available for OpcodeJump")
- }
- i.u1 = 1
-}
-
-// AsBrz initializes this instruction as a branch-if-zero instruction with OpcodeBrz.
-func (i *Instruction) AsBrz(v Value, args Values, target BasicBlock) {
- i.opcode = OpcodeBrz
- i.v = v
- i.vs = args
- i.rValue = Value(target.ID())
-}
-
-// AsBrnz initializes this instruction as a branch-if-not-zero instruction with OpcodeBrnz.
-func (i *Instruction) AsBrnz(v Value, args Values, target BasicBlock) *Instruction {
- i.opcode = OpcodeBrnz
- i.v = v
- i.vs = args
- i.rValue = Value(target.ID())
- return i
-}
-
-// AsBrTable initializes this instruction as a branch-table instruction with OpcodeBrTable.
-// targets is a list of basic block IDs cast to Values.
-func (i *Instruction) AsBrTable(index Value, targets Values) {
- i.opcode = OpcodeBrTable
- i.v = index
- i.rValues = targets
-}
-
-// AsCall initializes this instruction as a call instruction with OpcodeCall.
-func (i *Instruction) AsCall(ref FuncRef, sig *Signature, args Values) {
- i.opcode = OpcodeCall
- i.u1 = uint64(ref)
- i.vs = args
- i.u2 = uint64(sig.ID)
- sig.used = true
-}
-
-// CallData returns the call data for this instruction necessary for backends.
-func (i *Instruction) CallData() (ref FuncRef, sigID SignatureID, args []Value) {
- if i.opcode != OpcodeCall {
- panic("BUG: CallData only available for OpcodeCall")
- }
- ref = FuncRef(i.u1)
- sigID = SignatureID(i.u2)
- args = i.vs.View()
- return
-}
-
-// AsCallIndirect initializes this instruction as a call-indirect instruction with OpcodeCallIndirect.
-func (i *Instruction) AsCallIndirect(funcPtr Value, sig *Signature, args Values) *Instruction {
- i.opcode = OpcodeCallIndirect
- i.typ = TypeF64
- i.vs = args
- i.v = funcPtr
- i.u1 = uint64(sig.ID)
- sig.used = true
- return i
-}
-
-// AsCallGoRuntimeMemmove is the same as AsCallIndirect, but with a special flag set to indicate that it is a call to the Go runtime memmove function.
-func (i *Instruction) AsCallGoRuntimeMemmove(funcPtr Value, sig *Signature, args Values) *Instruction {
- i.AsCallIndirect(funcPtr, sig, args)
- i.u2 = 1
- return i
-}
-
-// CallIndirectData returns the call indirect data for this instruction necessary for backends.
-func (i *Instruction) CallIndirectData() (funcPtr Value, sigID SignatureID, args []Value, isGoMemmove bool) {
- if i.opcode != OpcodeCallIndirect {
- panic("BUG: CallIndirectData only available for OpcodeCallIndirect")
- }
- funcPtr = i.v
- sigID = SignatureID(i.u1)
- args = i.vs.View()
- isGoMemmove = i.u2 == 1
- return
-}
-
-// AsClz initializes this instruction as a Count Leading Zeroes instruction with OpcodeClz.
-func (i *Instruction) AsClz(x Value) {
- i.opcode = OpcodeClz
- i.v = x
- i.typ = x.Type()
-}
-
-// AsCtz initializes this instruction as a Count Trailing Zeroes instruction with OpcodeCtz.
-func (i *Instruction) AsCtz(x Value) {
- i.opcode = OpcodeCtz
- i.v = x
- i.typ = x.Type()
-}
-
-// AsPopcnt initializes this instruction as a Population Count instruction with OpcodePopcnt.
-func (i *Instruction) AsPopcnt(x Value) {
- i.opcode = OpcodePopcnt
- i.v = x
- i.typ = x.Type()
-}
-
-// AsFneg initializes this instruction as an instruction with OpcodeFneg.
-func (i *Instruction) AsFneg(x Value) *Instruction {
- i.opcode = OpcodeFneg
- i.v = x
- i.typ = x.Type()
- return i
-}
-
-// AsSqrt initializes this instruction as an instruction with OpcodeSqrt.
-func (i *Instruction) AsSqrt(x Value) *Instruction {
- i.opcode = OpcodeSqrt
- i.v = x
- i.typ = x.Type()
- return i
-}
-
-// AsFabs initializes this instruction as an instruction with OpcodeFabs.
-func (i *Instruction) AsFabs(x Value) *Instruction {
- i.opcode = OpcodeFabs
- i.v = x
- i.typ = x.Type()
- return i
-}
-
-// AsFcopysign initializes this instruction as an instruction with OpcodeFcopysign.
-func (i *Instruction) AsFcopysign(x, y Value) *Instruction {
- i.opcode = OpcodeFcopysign
- i.v = x
- i.v2 = y
- i.typ = x.Type()
- return i
-}
-
-// AsCeil initializes this instruction as an instruction with OpcodeCeil.
-func (i *Instruction) AsCeil(x Value) *Instruction {
- i.opcode = OpcodeCeil
- i.v = x
- i.typ = x.Type()
- return i
-}
-
-// AsFloor initializes this instruction as an instruction with OpcodeFloor.
-func (i *Instruction) AsFloor(x Value) *Instruction {
- i.opcode = OpcodeFloor
- i.v = x
- i.typ = x.Type()
- return i
-}
-
-// AsTrunc initializes this instruction as an instruction with OpcodeTrunc.
-func (i *Instruction) AsTrunc(x Value) *Instruction {
- i.opcode = OpcodeTrunc
- i.v = x
- i.typ = x.Type()
- return i
-}
-
-// AsNearest initializes this instruction as an instruction with OpcodeNearest.
-func (i *Instruction) AsNearest(x Value) *Instruction {
- i.opcode = OpcodeNearest
- i.v = x
- i.typ = x.Type()
- return i
-}
-
-// AsBitcast initializes this instruction as an instruction with OpcodeBitcast.
-func (i *Instruction) AsBitcast(x Value, dstType Type) *Instruction {
- i.opcode = OpcodeBitcast
- i.v = x
- i.typ = dstType
- return i
-}
-
-// BitcastData returns the operands for a bitcast instruction.
-func (i *Instruction) BitcastData() (x Value, dstType Type) {
- return i.v, i.typ
-}
-
-// AsFdemote initializes this instruction as an instruction with OpcodeFdemote.
-func (i *Instruction) AsFdemote(x Value) {
- i.opcode = OpcodeFdemote
- i.v = x
- i.typ = TypeF32
-}
-
-// AsFpromote initializes this instruction as an instruction with OpcodeFpromote.
-func (i *Instruction) AsFpromote(x Value) {
- i.opcode = OpcodeFpromote
- i.v = x
- i.typ = TypeF64
-}
-
-// AsFcvtFromInt initializes this instruction as an instruction with either OpcodeFcvtFromUint or OpcodeFcvtFromSint
-func (i *Instruction) AsFcvtFromInt(x Value, signed bool, dst64bit bool) *Instruction {
- if signed {
- i.opcode = OpcodeFcvtFromSint
- } else {
- i.opcode = OpcodeFcvtFromUint
- }
- i.v = x
- if dst64bit {
- i.typ = TypeF64
- } else {
- i.typ = TypeF32
- }
- return i
-}
-
-// AsFcvtToInt initializes this instruction as an instruction with either OpcodeFcvtToUint or OpcodeFcvtToSint
-func (i *Instruction) AsFcvtToInt(x, ctx Value, signed bool, dst64bit bool, sat bool) *Instruction {
- switch {
- case signed && !sat:
- i.opcode = OpcodeFcvtToSint
- case !signed && !sat:
- i.opcode = OpcodeFcvtToUint
- case signed && sat:
- i.opcode = OpcodeFcvtToSintSat
- case !signed && sat:
- i.opcode = OpcodeFcvtToUintSat
- }
- i.v = x
- i.v2 = ctx
- if dst64bit {
- i.typ = TypeI64
- } else {
- i.typ = TypeI32
- }
- return i
-}
-
-// AsVFcvtToIntSat initializes this instruction as an instruction with either OpcodeVFcvtToSintSat or OpcodeVFcvtToUintSat
-func (i *Instruction) AsVFcvtToIntSat(x Value, lane VecLane, signed bool) *Instruction {
- if signed {
- i.opcode = OpcodeVFcvtToSintSat
- } else {
- i.opcode = OpcodeVFcvtToUintSat
- }
- i.v = x
- i.u1 = uint64(lane)
- return i
-}
-
-// AsVFcvtFromInt initializes this instruction as an instruction with either OpcodeVFcvtToSintSat or OpcodeVFcvtToUintSat
-func (i *Instruction) AsVFcvtFromInt(x Value, lane VecLane, signed bool) *Instruction {
- if signed {
- i.opcode = OpcodeVFcvtFromSint
- } else {
- i.opcode = OpcodeVFcvtFromUint
- }
- i.v = x
- i.u1 = uint64(lane)
- return i
-}
-
-// AsNarrow initializes this instruction as an instruction with either OpcodeSnarrow or OpcodeUnarrow
-func (i *Instruction) AsNarrow(x, y Value, lane VecLane, signed bool) *Instruction {
- if signed {
- i.opcode = OpcodeSnarrow
- } else {
- i.opcode = OpcodeUnarrow
- }
- i.v = x
- i.v2 = y
- i.u1 = uint64(lane)
- return i
-}
-
-// AsFvpromoteLow initializes this instruction as an instruction with OpcodeFvpromoteLow
-func (i *Instruction) AsFvpromoteLow(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeFvpromoteLow
- i.v = x
- i.u1 = uint64(lane)
- return i
-}
-
-// AsFvdemote initializes this instruction as an instruction with OpcodeFvdemote
-func (i *Instruction) AsFvdemote(x Value, lane VecLane) *Instruction {
- i.opcode = OpcodeFvdemote
- i.v = x
- i.u1 = uint64(lane)
- return i
-}
-
-// AsSExtend initializes this instruction as a sign extension instruction with OpcodeSExtend.
-func (i *Instruction) AsSExtend(v Value, from, to byte) *Instruction {
- i.opcode = OpcodeSExtend
- i.v = v
- i.u1 = uint64(from)<<8 | uint64(to)
- if to == 64 {
- i.typ = TypeI64
- } else {
- i.typ = TypeI32
- }
- return i
-}
-
-// AsUExtend initializes this instruction as an unsigned extension instruction with OpcodeUExtend.
-func (i *Instruction) AsUExtend(v Value, from, to byte) *Instruction {
- i.opcode = OpcodeUExtend
- i.v = v
- i.u1 = uint64(from)<<8 | uint64(to)
- if to == 64 {
- i.typ = TypeI64
- } else {
- i.typ = TypeI32
- }
- return i
-}
-
-func (i *Instruction) ExtendData() (from, to byte, signed bool) {
- if i.opcode != OpcodeSExtend && i.opcode != OpcodeUExtend {
- panic("BUG: ExtendData only available for OpcodeSExtend and OpcodeUExtend")
- }
- from = byte(i.u1 >> 8)
- to = byte(i.u1)
- signed = i.opcode == OpcodeSExtend
- return
-}
-
-// AsSelect initializes this instruction as an unsigned extension instruction with OpcodeSelect.
-func (i *Instruction) AsSelect(c, x, y Value) *Instruction {
- i.opcode = OpcodeSelect
- i.v = c
- i.v2 = x
- i.v3 = y
- i.typ = x.Type()
- return i
-}
-
-// SelectData returns the select data for this instruction necessary for backends.
-func (i *Instruction) SelectData() (c, x, y Value) {
- c = i.v
- x = i.v2
- y = i.v3
- return
-}
-
-// ExtendFromToBits returns the from and to bit size for the extension instruction.
-func (i *Instruction) ExtendFromToBits() (from, to byte) {
- from = byte(i.u1 >> 8)
- to = byte(i.u1)
- return
-}
-
-// Format returns a string representation of this instruction with the given builder.
-// For debugging purposes only.
-func (i *Instruction) Format(b Builder) string {
- var instSuffix string
- switch i.opcode {
- case OpcodeExitWithCode:
- instSuffix = fmt.Sprintf(" %s, %s", i.v.Format(b), wazevoapi.ExitCode(i.u1))
- case OpcodeExitIfTrueWithCode:
- instSuffix = fmt.Sprintf(" %s, %s, %s", i.v2.Format(b), i.v.Format(b), wazevoapi.ExitCode(i.u1))
- case OpcodeIadd, OpcodeIsub, OpcodeImul, OpcodeFadd, OpcodeFsub, OpcodeFmin, OpcodeFmax, OpcodeFdiv, OpcodeFmul:
- instSuffix = fmt.Sprintf(" %s, %s", i.v.Format(b), i.v2.Format(b))
- case OpcodeIcmp:
- instSuffix = fmt.Sprintf(" %s, %s, %s", IntegerCmpCond(i.u1), i.v.Format(b), i.v2.Format(b))
- case OpcodeFcmp:
- instSuffix = fmt.Sprintf(" %s, %s, %s", FloatCmpCond(i.u1), i.v.Format(b), i.v2.Format(b))
- case OpcodeSExtend, OpcodeUExtend:
- instSuffix = fmt.Sprintf(" %s, %d->%d", i.v.Format(b), i.u1>>8, i.u1&0xff)
- case OpcodeCall, OpcodeCallIndirect:
- view := i.vs.View()
- vs := make([]string, len(view))
- for idx := range vs {
- vs[idx] = view[idx].Format(b)
- }
- if i.opcode == OpcodeCallIndirect {
- instSuffix = fmt.Sprintf(" %s:%s, %s", i.v.Format(b), SignatureID(i.u1), strings.Join(vs, ", "))
- } else {
- instSuffix = fmt.Sprintf(" %s:%s, %s", FuncRef(i.u1), SignatureID(i.u2), strings.Join(vs, ", "))
- }
- case OpcodeStore, OpcodeIstore8, OpcodeIstore16, OpcodeIstore32:
- instSuffix = fmt.Sprintf(" %s, %s, %#x", i.v.Format(b), i.v2.Format(b), uint32(i.u1))
- case OpcodeLoad, OpcodeVZeroExtLoad:
- instSuffix = fmt.Sprintf(" %s, %#x", i.v.Format(b), int32(i.u1))
- case OpcodeLoadSplat:
- instSuffix = fmt.Sprintf(".%s %s, %#x", VecLane(i.u2), i.v.Format(b), int32(i.u1))
- case OpcodeUload8, OpcodeUload16, OpcodeUload32, OpcodeSload8, OpcodeSload16, OpcodeSload32:
- instSuffix = fmt.Sprintf(" %s, %#x", i.v.Format(b), int32(i.u1))
- case OpcodeSelect, OpcodeVbitselect:
- instSuffix = fmt.Sprintf(" %s, %s, %s", i.v.Format(b), i.v2.Format(b), i.v3.Format(b))
- case OpcodeIconst:
- switch i.typ {
- case TypeI32:
- instSuffix = fmt.Sprintf("_32 %#x", uint32(i.u1))
- case TypeI64:
- instSuffix = fmt.Sprintf("_64 %#x", i.u1)
- }
- case OpcodeVconst:
- instSuffix = fmt.Sprintf(" %016x %016x", i.u1, i.u2)
- case OpcodeF32const:
- instSuffix = fmt.Sprintf(" %f", math.Float32frombits(uint32(i.u1)))
- case OpcodeF64const:
- instSuffix = fmt.Sprintf(" %f", math.Float64frombits(i.u1))
- case OpcodeReturn:
- view := i.vs.View()
- if len(view) == 0 {
- break
- }
- vs := make([]string, len(view))
- for idx := range vs {
- vs[idx] = view[idx].Format(b)
- }
- instSuffix = fmt.Sprintf(" %s", strings.Join(vs, ", "))
- case OpcodeJump:
- view := i.vs.View()
- vs := make([]string, len(view)+1)
- if i.IsFallthroughJump() {
- vs[0] = " fallthrough"
- } else {
- blockId := BasicBlockID(i.rValue)
- vs[0] = " " + b.BasicBlock(blockId).Name()
- }
- for idx := range view {
- vs[idx+1] = view[idx].Format(b)
- }
-
- instSuffix = strings.Join(vs, ", ")
- case OpcodeBrz, OpcodeBrnz:
- view := i.vs.View()
- vs := make([]string, len(view)+2)
- vs[0] = " " + i.v.Format(b)
- blockId := BasicBlockID(i.rValue)
- vs[1] = b.BasicBlock(blockId).Name()
- for idx := range view {
- vs[idx+2] = view[idx].Format(b)
- }
- instSuffix = strings.Join(vs, ", ")
- case OpcodeBrTable:
- // `BrTable index, [label1, label2, ... labelN]`
- instSuffix = fmt.Sprintf(" %s", i.v.Format(b))
- instSuffix += ", ["
- for i, target := range i.rValues.View() {
- blk := b.BasicBlock(BasicBlockID(target))
- if i == 0 {
- instSuffix += blk.Name()
- } else {
- instSuffix += ", " + blk.Name()
- }
- }
- instSuffix += "]"
- case OpcodeBand, OpcodeBor, OpcodeBxor, OpcodeRotr, OpcodeRotl, OpcodeIshl, OpcodeSshr, OpcodeUshr,
- OpcodeSdiv, OpcodeUdiv, OpcodeFcopysign, OpcodeSrem, OpcodeUrem,
- OpcodeVbnot, OpcodeVbxor, OpcodeVbor, OpcodeVband, OpcodeVbandnot, OpcodeVIcmp, OpcodeVFcmp:
- instSuffix = fmt.Sprintf(" %s, %s", i.v.Format(b), i.v2.Format(b))
- case OpcodeUndefined:
- case OpcodeClz, OpcodeCtz, OpcodePopcnt, OpcodeFneg, OpcodeFcvtToSint, OpcodeFcvtToUint, OpcodeFcvtFromSint,
- OpcodeFcvtFromUint, OpcodeFcvtToSintSat, OpcodeFcvtToUintSat, OpcodeFdemote, OpcodeFpromote, OpcodeIreduce, OpcodeBitcast, OpcodeSqrt, OpcodeFabs,
- OpcodeCeil, OpcodeFloor, OpcodeTrunc, OpcodeNearest:
- instSuffix = " " + i.v.Format(b)
- case OpcodeVIadd, OpcodeExtIaddPairwise, OpcodeVSaddSat, OpcodeVUaddSat, OpcodeVIsub, OpcodeVSsubSat, OpcodeVUsubSat,
- OpcodeVImin, OpcodeVUmin, OpcodeVImax, OpcodeVUmax, OpcodeVImul, OpcodeVAvgRound,
- OpcodeVFadd, OpcodeVFsub, OpcodeVFmul, OpcodeVFdiv,
- OpcodeVIshl, OpcodeVSshr, OpcodeVUshr,
- OpcodeVFmin, OpcodeVFmax, OpcodeVMinPseudo, OpcodeVMaxPseudo,
- OpcodeSnarrow, OpcodeUnarrow, OpcodeSwizzle, OpcodeSqmulRoundSat:
- instSuffix = fmt.Sprintf(".%s %s, %s", VecLane(i.u1), i.v.Format(b), i.v2.Format(b))
- case OpcodeVIabs, OpcodeVIneg, OpcodeVIpopcnt, OpcodeVhighBits, OpcodeVallTrue, OpcodeVanyTrue,
- OpcodeVFabs, OpcodeVFneg, OpcodeVSqrt, OpcodeVCeil, OpcodeVFloor, OpcodeVTrunc, OpcodeVNearest,
- OpcodeVFcvtToUintSat, OpcodeVFcvtToSintSat, OpcodeVFcvtFromUint, OpcodeVFcvtFromSint,
- OpcodeFvpromoteLow, OpcodeFvdemote, OpcodeSwidenLow, OpcodeUwidenLow, OpcodeSwidenHigh, OpcodeUwidenHigh,
- OpcodeSplat:
- instSuffix = fmt.Sprintf(".%s %s", VecLane(i.u1), i.v.Format(b))
- case OpcodeExtractlane:
- var signedness string
- if i.u1 != 0 {
- signedness = "signed"
- } else {
- signedness = "unsigned"
- }
- instSuffix = fmt.Sprintf(".%s %d, %s (%s)", VecLane(i.u2), 0x0000FFFF&i.u1, i.v.Format(b), signedness)
- case OpcodeInsertlane:
- instSuffix = fmt.Sprintf(".%s %d, %s, %s", VecLane(i.u2), i.u1, i.v.Format(b), i.v2.Format(b))
- case OpcodeShuffle:
- lanes := make([]byte, 16)
- for idx := 0; idx < 8; idx++ {
- lanes[idx] = byte(i.u1 >> (8 * idx))
- }
- for idx := 0; idx < 8; idx++ {
- lanes[idx+8] = byte(i.u2 >> (8 * idx))
- }
- // Prints Shuffle.[0 1 2 3 4 5 6 7 ...] v2, v3
- instSuffix = fmt.Sprintf(".%v %s, %s", lanes, i.v.Format(b), i.v2.Format(b))
- case OpcodeAtomicRmw:
- instSuffix = fmt.Sprintf(" %s_%d, %s, %s", AtomicRmwOp(i.u1), 8*i.u2, i.v.Format(b), i.v2.Format(b))
- case OpcodeAtomicLoad:
- instSuffix = fmt.Sprintf("_%d, %s", 8*i.u1, i.v.Format(b))
- case OpcodeAtomicStore:
- instSuffix = fmt.Sprintf("_%d, %s, %s", 8*i.u1, i.v.Format(b), i.v2.Format(b))
- case OpcodeAtomicCas:
- instSuffix = fmt.Sprintf("_%d, %s, %s, %s", 8*i.u1, i.v.Format(b), i.v2.Format(b), i.v3.Format(b))
- case OpcodeFence:
- instSuffix = fmt.Sprintf(" %d", i.u1)
- case OpcodeWideningPairwiseDotProductS:
- instSuffix = fmt.Sprintf(" %s, %s", i.v.Format(b), i.v2.Format(b))
- default:
- panic(fmt.Sprintf("TODO: format for %s", i.opcode))
- }
-
- instr := i.opcode.String() + instSuffix
-
- var rvs []string
- r1, rs := i.Returns()
- if r1.Valid() {
- rvs = append(rvs, r1.formatWithType(b))
- }
-
- for _, v := range rs {
- rvs = append(rvs, v.formatWithType(b))
- }
-
- if len(rvs) > 0 {
- return fmt.Sprintf("%s = %s", strings.Join(rvs, ", "), instr)
- } else {
- return instr
- }
-}
-
-// addArgumentBranchInst adds an argument to this instruction.
-func (i *Instruction) addArgumentBranchInst(b *builder, v Value) {
- switch i.opcode {
- case OpcodeJump, OpcodeBrz, OpcodeBrnz:
- i.vs = i.vs.Append(&b.varLengthPool, v)
- default:
- panic("BUG: " + i.opcode.String())
- }
-}
-
-// Constant returns true if this instruction is a constant instruction.
-func (i *Instruction) Constant() bool {
- switch i.opcode {
- case OpcodeIconst, OpcodeF32const, OpcodeF64const:
- return true
- }
- return false
-}
-
-// ConstantVal returns the constant value of this instruction.
-// How to interpret the return value depends on the opcode.
-func (i *Instruction) ConstantVal() (ret uint64) {
- switch i.opcode {
- case OpcodeIconst, OpcodeF32const, OpcodeF64const:
- ret = i.u1
- default:
- panic("TODO")
- }
- return
-}
-
-// String implements fmt.Stringer.
-func (o Opcode) String() (ret string) {
- switch o {
- case OpcodeInvalid:
- return "invalid"
- case OpcodeUndefined:
- return "Undefined"
- case OpcodeJump:
- return "Jump"
- case OpcodeBrz:
- return "Brz"
- case OpcodeBrnz:
- return "Brnz"
- case OpcodeBrTable:
- return "BrTable"
- case OpcodeExitWithCode:
- return "Exit"
- case OpcodeExitIfTrueWithCode:
- return "ExitIfTrue"
- case OpcodeReturn:
- return "Return"
- case OpcodeCall:
- return "Call"
- case OpcodeCallIndirect:
- return "CallIndirect"
- case OpcodeSplat:
- return "Splat"
- case OpcodeSwizzle:
- return "Swizzle"
- case OpcodeInsertlane:
- return "Insertlane"
- case OpcodeExtractlane:
- return "Extractlane"
- case OpcodeLoad:
- return "Load"
- case OpcodeLoadSplat:
- return "LoadSplat"
- case OpcodeStore:
- return "Store"
- case OpcodeUload8:
- return "Uload8"
- case OpcodeSload8:
- return "Sload8"
- case OpcodeIstore8:
- return "Istore8"
- case OpcodeUload16:
- return "Uload16"
- case OpcodeSload16:
- return "Sload16"
- case OpcodeIstore16:
- return "Istore16"
- case OpcodeUload32:
- return "Uload32"
- case OpcodeSload32:
- return "Sload32"
- case OpcodeIstore32:
- return "Istore32"
- case OpcodeIconst:
- return "Iconst"
- case OpcodeF32const:
- return "F32const"
- case OpcodeF64const:
- return "F64const"
- case OpcodeVconst:
- return "Vconst"
- case OpcodeShuffle:
- return "Shuffle"
- case OpcodeSelect:
- return "Select"
- case OpcodeVanyTrue:
- return "VanyTrue"
- case OpcodeVallTrue:
- return "VallTrue"
- case OpcodeVhighBits:
- return "VhighBits"
- case OpcodeIcmp:
- return "Icmp"
- case OpcodeIcmpImm:
- return "IcmpImm"
- case OpcodeVIcmp:
- return "VIcmp"
- case OpcodeIadd:
- return "Iadd"
- case OpcodeIsub:
- return "Isub"
- case OpcodeImul:
- return "Imul"
- case OpcodeUdiv:
- return "Udiv"
- case OpcodeSdiv:
- return "Sdiv"
- case OpcodeUrem:
- return "Urem"
- case OpcodeSrem:
- return "Srem"
- case OpcodeBand:
- return "Band"
- case OpcodeBor:
- return "Bor"
- case OpcodeBxor:
- return "Bxor"
- case OpcodeBnot:
- return "Bnot"
- case OpcodeRotl:
- return "Rotl"
- case OpcodeRotr:
- return "Rotr"
- case OpcodeIshl:
- return "Ishl"
- case OpcodeUshr:
- return "Ushr"
- case OpcodeSshr:
- return "Sshr"
- case OpcodeClz:
- return "Clz"
- case OpcodeCtz:
- return "Ctz"
- case OpcodePopcnt:
- return "Popcnt"
- case OpcodeFcmp:
- return "Fcmp"
- case OpcodeFadd:
- return "Fadd"
- case OpcodeFsub:
- return "Fsub"
- case OpcodeFmul:
- return "Fmul"
- case OpcodeFdiv:
- return "Fdiv"
- case OpcodeSqmulRoundSat:
- return "SqmulRoundSat"
- case OpcodeSqrt:
- return "Sqrt"
- case OpcodeFneg:
- return "Fneg"
- case OpcodeFabs:
- return "Fabs"
- case OpcodeFcopysign:
- return "Fcopysign"
- case OpcodeFmin:
- return "Fmin"
- case OpcodeFmax:
- return "Fmax"
- case OpcodeCeil:
- return "Ceil"
- case OpcodeFloor:
- return "Floor"
- case OpcodeTrunc:
- return "Trunc"
- case OpcodeNearest:
- return "Nearest"
- case OpcodeBitcast:
- return "Bitcast"
- case OpcodeIreduce:
- return "Ireduce"
- case OpcodeSnarrow:
- return "Snarrow"
- case OpcodeUnarrow:
- return "Unarrow"
- case OpcodeSwidenLow:
- return "SwidenLow"
- case OpcodeSwidenHigh:
- return "SwidenHigh"
- case OpcodeUwidenLow:
- return "UwidenLow"
- case OpcodeUwidenHigh:
- return "UwidenHigh"
- case OpcodeExtIaddPairwise:
- return "IaddPairwise"
- case OpcodeWideningPairwiseDotProductS:
- return "WideningPairwiseDotProductS"
- case OpcodeUExtend:
- return "UExtend"
- case OpcodeSExtend:
- return "SExtend"
- case OpcodeFpromote:
- return "Fpromote"
- case OpcodeFdemote:
- return "Fdemote"
- case OpcodeFvdemote:
- return "Fvdemote"
- case OpcodeFcvtToUint:
- return "FcvtToUint"
- case OpcodeFcvtToSint:
- return "FcvtToSint"
- case OpcodeFcvtToUintSat:
- return "FcvtToUintSat"
- case OpcodeFcvtToSintSat:
- return "FcvtToSintSat"
- case OpcodeFcvtFromUint:
- return "FcvtFromUint"
- case OpcodeFcvtFromSint:
- return "FcvtFromSint"
- case OpcodeAtomicRmw:
- return "AtomicRmw"
- case OpcodeAtomicCas:
- return "AtomicCas"
- case OpcodeAtomicLoad:
- return "AtomicLoad"
- case OpcodeAtomicStore:
- return "AtomicStore"
- case OpcodeFence:
- return "Fence"
- case OpcodeVbor:
- return "Vbor"
- case OpcodeVbxor:
- return "Vbxor"
- case OpcodeVband:
- return "Vband"
- case OpcodeVbandnot:
- return "Vbandnot"
- case OpcodeVbnot:
- return "Vbnot"
- case OpcodeVbitselect:
- return "Vbitselect"
- case OpcodeVIadd:
- return "VIadd"
- case OpcodeVSaddSat:
- return "VSaddSat"
- case OpcodeVUaddSat:
- return "VUaddSat"
- case OpcodeVSsubSat:
- return "VSsubSat"
- case OpcodeVUsubSat:
- return "VUsubSat"
- case OpcodeVAvgRound:
- return "OpcodeVAvgRound"
- case OpcodeVIsub:
- return "VIsub"
- case OpcodeVImin:
- return "VImin"
- case OpcodeVUmin:
- return "VUmin"
- case OpcodeVImax:
- return "VImax"
- case OpcodeVUmax:
- return "VUmax"
- case OpcodeVImul:
- return "VImul"
- case OpcodeVIabs:
- return "VIabs"
- case OpcodeVIneg:
- return "VIneg"
- case OpcodeVIpopcnt:
- return "VIpopcnt"
- case OpcodeVIshl:
- return "VIshl"
- case OpcodeVUshr:
- return "VUshr"
- case OpcodeVSshr:
- return "VSshr"
- case OpcodeVFabs:
- return "VFabs"
- case OpcodeVFmax:
- return "VFmax"
- case OpcodeVFmin:
- return "VFmin"
- case OpcodeVFneg:
- return "VFneg"
- case OpcodeVFadd:
- return "VFadd"
- case OpcodeVFsub:
- return "VFsub"
- case OpcodeVFmul:
- return "VFmul"
- case OpcodeVFdiv:
- return "VFdiv"
- case OpcodeVFcmp:
- return "VFcmp"
- case OpcodeVCeil:
- return "VCeil"
- case OpcodeVFloor:
- return "VFloor"
- case OpcodeVTrunc:
- return "VTrunc"
- case OpcodeVNearest:
- return "VNearest"
- case OpcodeVMaxPseudo:
- return "VMaxPseudo"
- case OpcodeVMinPseudo:
- return "VMinPseudo"
- case OpcodeVSqrt:
- return "VSqrt"
- case OpcodeVFcvtToUintSat:
- return "VFcvtToUintSat"
- case OpcodeVFcvtToSintSat:
- return "VFcvtToSintSat"
- case OpcodeVFcvtFromUint:
- return "VFcvtFromUint"
- case OpcodeVFcvtFromSint:
- return "VFcvtFromSint"
- case OpcodeFvpromoteLow:
- return "FvpromoteLow"
- case OpcodeVZeroExtLoad:
- return "VZeroExtLoad"
- }
- panic(fmt.Sprintf("unknown opcode %d", o))
-}