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