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