1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef jit_shared_LIR_shared_h
8 #define jit_shared_LIR_shared_h
9 
10 #include "mozilla/Maybe.h"
11 #include "jit/AtomicOp.h"
12 #include "jit/shared/Assembler-shared.h"
13 #include "util/Memory.h"
14 
15 // This file declares LIR instructions that are common to every platform.
16 
17 namespace js {
18 namespace jit {
19 
20 LIR_OPCODE_CLASS_GENERATED
21 
22 class LBox : public LInstructionHelper<BOX_PIECES, 1, 0> {
23   MIRType type_;
24 
25  public:
26   LIR_HEADER(Box);
27 
LBox(const LAllocation & payload,MIRType type)28   LBox(const LAllocation& payload, MIRType type)
29       : LInstructionHelper(classOpcode), type_(type) {
30     setOperand(0, payload);
31   }
32 
type()33   MIRType type() const { return type_; }
extraName()34   const char* extraName() const { return StringFromMIRType(type_); }
35 };
36 
37 template <size_t Temps, size_t ExtraUses = 0>
38 class LBinaryMath : public LInstructionHelper<1, 2 + ExtraUses, Temps> {
39  protected:
LBinaryMath(LNode::Opcode opcode)40   explicit LBinaryMath(LNode::Opcode opcode)
41       : LInstructionHelper<1, 2 + ExtraUses, Temps>(opcode) {}
42 
43  public:
lhs()44   const LAllocation* lhs() { return this->getOperand(0); }
rhs()45   const LAllocation* rhs() { return this->getOperand(1); }
46 };
47 
48 template <size_t Temps, size_t ExtraUses = 0>
49 class LUnaryMath : public LInstructionHelper<1, 1 + ExtraUses, Temps> {
50  protected:
LUnaryMath(LNode::Opcode opcode)51   explicit LUnaryMath(LNode::Opcode opcode)
52       : LInstructionHelper<1, 1 + ExtraUses, Temps>(opcode) {}
53 
54  public:
input()55   const LAllocation* input() { return this->getOperand(0); }
56 };
57 
58 // An LOsiPoint captures a snapshot after a call and ensures enough space to
59 // patch in a call to the invalidation mechanism.
60 //
61 // Note: LSafepoints are 1:1 with LOsiPoints, so it holds a reference to the
62 // corresponding LSafepoint to inform it of the LOsiPoint's masm offset when it
63 // gets GC'd.
64 class LOsiPoint : public LInstructionHelper<0, 0, 0> {
65   LSafepoint* safepoint_;
66 
67  public:
LOsiPoint(LSafepoint * safepoint,LSnapshot * snapshot)68   LOsiPoint(LSafepoint* safepoint, LSnapshot* snapshot)
69       : LInstructionHelper(classOpcode), safepoint_(safepoint) {
70     MOZ_ASSERT(safepoint && snapshot);
71     assignSnapshot(snapshot);
72   }
73 
associatedSafepoint()74   LSafepoint* associatedSafepoint() { return safepoint_; }
75 
76   LIR_HEADER(OsiPoint)
77 };
78 
79 class LMove {
80   LAllocation from_;
81   LAllocation to_;
82   LDefinition::Type type_;
83 
84  public:
LMove(LAllocation from,LAllocation to,LDefinition::Type type)85   LMove(LAllocation from, LAllocation to, LDefinition::Type type)
86       : from_(from), to_(to), type_(type) {}
87 
from()88   LAllocation from() const { return from_; }
to()89   LAllocation to() const { return to_; }
type()90   LDefinition::Type type() const { return type_; }
91 };
92 
93 class LMoveGroup : public LInstructionHelper<0, 0, 0> {
94   js::Vector<LMove, 2, JitAllocPolicy> moves_;
95 
96 #ifdef JS_CODEGEN_X86
97   // Optional general register available for use when executing moves.
98   LAllocation scratchRegister_;
99 #endif
100 
LMoveGroup(TempAllocator & alloc)101   explicit LMoveGroup(TempAllocator& alloc)
102       : LInstructionHelper(classOpcode), moves_(alloc) {}
103 
104  public:
LIR_HEADER(MoveGroup)105   LIR_HEADER(MoveGroup)
106 
107   static LMoveGroup* New(TempAllocator& alloc) {
108     return new (alloc) LMoveGroup(alloc);
109   }
110 
111   void printOperands(GenericPrinter& out);
112 
113   // Add a move which takes place simultaneously with all others in the group.
114   bool add(LAllocation from, LAllocation to, LDefinition::Type type);
115 
116   // Add a move which takes place after existing moves in the group.
117   bool addAfter(LAllocation from, LAllocation to, LDefinition::Type type);
118 
numMoves()119   size_t numMoves() const { return moves_.length(); }
getMove(size_t i)120   const LMove& getMove(size_t i) const { return moves_[i]; }
121 
122 #ifdef JS_CODEGEN_X86
setScratchRegister(Register reg)123   void setScratchRegister(Register reg) { scratchRegister_ = LGeneralReg(reg); }
maybeScratchRegister()124   LAllocation maybeScratchRegister() { return scratchRegister_; }
125 #endif
126 
uses(Register reg)127   bool uses(Register reg) {
128     for (size_t i = 0; i < numMoves(); i++) {
129       LMove move = getMove(i);
130       if (move.from() == LGeneralReg(reg) || move.to() == LGeneralReg(reg)) {
131         return true;
132       }
133     }
134     return false;
135   }
136 };
137 
138 // A constant Value.
139 class LValue : public LInstructionHelper<BOX_PIECES, 0, 0> {
140   Value v_;
141 
142  public:
LIR_HEADER(Value)143   LIR_HEADER(Value)
144 
145   explicit LValue(const Value& v) : LInstructionHelper(classOpcode), v_(v) {}
146 
value()147   Value value() const { return v_; }
148 };
149 
150 // Base class for control instructions (goto, branch, etc.)
151 template <size_t Succs, size_t Operands, size_t Temps>
152 class LControlInstructionHelper
153     : public LInstructionHelper<0, Operands, Temps> {
154   mozilla::Array<MBasicBlock*, Succs> successors_;
155 
156  protected:
LControlInstructionHelper(LNode::Opcode opcode)157   explicit LControlInstructionHelper(LNode::Opcode opcode)
158       : LInstructionHelper<0, Operands, Temps>(opcode) {}
159 
160  public:
numSuccessors()161   size_t numSuccessors() const { return Succs; }
getSuccessor(size_t i)162   MBasicBlock* getSuccessor(size_t i) const { return successors_[i]; }
163 
setSuccessor(size_t i,MBasicBlock * successor)164   void setSuccessor(size_t i, MBasicBlock* successor) {
165     successors_[i] = successor;
166   }
167 };
168 
169 // Jumps to the start of a basic block.
170 class LGoto : public LControlInstructionHelper<1, 0, 0> {
171  public:
LIR_HEADER(Goto)172   LIR_HEADER(Goto)
173 
174   explicit LGoto(MBasicBlock* block) : LControlInstructionHelper(classOpcode) {
175     setSuccessor(0, block);
176   }
177 
target()178   MBasicBlock* target() const { return getSuccessor(0); }
179 };
180 
181 class LNewArray : public LInstructionHelper<1, 0, 1> {
182  public:
LIR_HEADER(NewArray)183   LIR_HEADER(NewArray)
184 
185   explicit LNewArray(const LDefinition& temp)
186       : LInstructionHelper(classOpcode) {
187     setTemp(0, temp);
188   }
189 
extraName()190   const char* extraName() const {
191     return mir()->isVMCall() ? "VMCall" : nullptr;
192   }
193 
temp()194   const LDefinition* temp() { return getTemp(0); }
195 
mir()196   MNewArray* mir() const { return mir_->toNewArray(); }
197 };
198 
199 class LNewObject : public LInstructionHelper<1, 0, 1> {
200  public:
LIR_HEADER(NewObject)201   LIR_HEADER(NewObject)
202 
203   explicit LNewObject(const LDefinition& temp)
204       : LInstructionHelper(classOpcode) {
205     setTemp(0, temp);
206   }
207 
extraName()208   const char* extraName() const {
209     return mir()->isVMCall() ? "VMCall" : nullptr;
210   }
211 
temp()212   const LDefinition* temp() { return getTemp(0); }
213 
mir()214   MNewObject* mir() const { return mir_->toNewObject(); }
215 };
216 
217 template <size_t Defs, size_t Ops>
218 class LWasmReinterpretBase : public LInstructionHelper<Defs, Ops, 0> {
219   typedef LInstructionHelper<Defs, Ops, 0> Base;
220 
221  protected:
LWasmReinterpretBase(LNode::Opcode opcode)222   explicit LWasmReinterpretBase(LNode::Opcode opcode) : Base(opcode) {}
223 
224  public:
input()225   const LAllocation* input() { return Base::getOperand(0); }
mir()226   MWasmReinterpret* mir() const { return Base::mir_->toWasmReinterpret(); }
227 };
228 
229 class LWasmReinterpret : public LWasmReinterpretBase<1, 1> {
230  public:
231   LIR_HEADER(WasmReinterpret);
LWasmReinterpret(const LAllocation & input)232   explicit LWasmReinterpret(const LAllocation& input)
233       : LWasmReinterpretBase(classOpcode) {
234     setOperand(0, input);
235   }
236 };
237 
238 class LWasmReinterpretFromI64 : public LWasmReinterpretBase<1, INT64_PIECES> {
239  public:
240   static const size_t Input = 0;
241 
242   LIR_HEADER(WasmReinterpretFromI64);
LWasmReinterpretFromI64(const LInt64Allocation & input)243   explicit LWasmReinterpretFromI64(const LInt64Allocation& input)
244       : LWasmReinterpretBase(classOpcode) {
245     setInt64Operand(Input, input);
246   }
247 };
248 
249 class LWasmReinterpretToI64 : public LWasmReinterpretBase<INT64_PIECES, 1> {
250  public:
251   LIR_HEADER(WasmReinterpretToI64);
LWasmReinterpretToI64(const LAllocation & input)252   explicit LWasmReinterpretToI64(const LAllocation& input)
253       : LWasmReinterpretBase(classOpcode) {
254     setOperand(0, input);
255   }
256 };
257 
258 namespace details {
259 template <size_t Defs, size_t Ops, size_t Temps>
260 class RotateBase : public LInstructionHelper<Defs, Ops, Temps> {
261   typedef LInstructionHelper<Defs, Ops, Temps> Base;
262 
263  protected:
RotateBase(LNode::Opcode opcode)264   explicit RotateBase(LNode::Opcode opcode) : Base(opcode) {}
265 
266  public:
mir()267   MRotate* mir() { return Base::mir_->toRotate(); }
268 };
269 }  // namespace details
270 
271 class LRotate : public details::RotateBase<1, 2, 0> {
272  public:
273   LIR_HEADER(Rotate);
274 
LRotate()275   LRotate() : RotateBase(classOpcode) {}
276 
input()277   const LAllocation* input() { return getOperand(0); }
count()278   LAllocation* count() { return getOperand(1); }
279 };
280 
281 class LRotateI64
282     : public details::RotateBase<INT64_PIECES, INT64_PIECES + 1, 1> {
283  public:
284   LIR_HEADER(RotateI64);
285 
LRotateI64()286   LRotateI64() : RotateBase(classOpcode) {
287     setTemp(0, LDefinition::BogusTemp());
288   }
289 
290   static const size_t Input = 0;
291   static const size_t Count = INT64_PIECES;
292 
input()293   const LInt64Allocation input() { return getInt64Operand(Input); }
temp()294   const LDefinition* temp() { return getTemp(0); }
count()295   LAllocation* count() { return getOperand(Count); }
296 };
297 
298 // Allocate a new arguments object for an inlined frame.
299 class LCreateInlinedArgumentsObject : public LVariadicInstruction<1, 1> {
300  public:
301   LIR_HEADER(CreateInlinedArgumentsObject)
302 
303   static const size_t CallObj = 0;
304   static const size_t Callee = 1;
305   static const size_t NumNonArgumentOperands = 2;
ArgIndex(size_t i)306   static size_t ArgIndex(size_t i) {
307     return NumNonArgumentOperands + BOX_PIECES * i;
308   }
309 
LCreateInlinedArgumentsObject(uint32_t numOperands,const LDefinition & temp)310   LCreateInlinedArgumentsObject(uint32_t numOperands, const LDefinition& temp)
311       : LVariadicInstruction(classOpcode, numOperands) {
312     setIsCall();
313     setTemp(0, temp);
314   }
315 
getCallObject()316   const LAllocation* getCallObject() { return getOperand(CallObj); }
getCallee()317   const LAllocation* getCallee() { return getOperand(Callee); }
318 
temp()319   const LDefinition* temp() { return getTemp(0); }
320 
mir()321   MCreateInlinedArgumentsObject* mir() const {
322     return mir_->toCreateInlinedArgumentsObject();
323   }
324 };
325 
326 class LGetInlinedArgument : public LVariadicInstruction<BOX_PIECES, 0> {
327  public:
328   LIR_HEADER(GetInlinedArgument)
329 
330   static const size_t Index = 0;
331   static const size_t NumNonArgumentOperands = 1;
ArgIndex(size_t i)332   static size_t ArgIndex(size_t i) {
333     return NumNonArgumentOperands + BOX_PIECES * i;
334   }
335 
LGetInlinedArgument(uint32_t numOperands)336   explicit LGetInlinedArgument(uint32_t numOperands)
337       : LVariadicInstruction(classOpcode, numOperands) {}
338 
getIndex()339   const LAllocation* getIndex() { return getOperand(Index); }
340 
mir()341   MGetInlinedArgument* mir() const { return mir_->toGetInlinedArgument(); }
342 };
343 
344 class LGetInlinedArgumentHole : public LVariadicInstruction<BOX_PIECES, 0> {
345  public:
346   LIR_HEADER(GetInlinedArgumentHole)
347 
348   static const size_t Index = 0;
349   static const size_t NumNonArgumentOperands = 1;
ArgIndex(size_t i)350   static size_t ArgIndex(size_t i) {
351     return NumNonArgumentOperands + BOX_PIECES * i;
352   }
353 
LGetInlinedArgumentHole(uint32_t numOperands)354   explicit LGetInlinedArgumentHole(uint32_t numOperands)
355       : LVariadicInstruction(classOpcode, numOperands) {}
356 
getIndex()357   const LAllocation* getIndex() { return getOperand(Index); }
358 
mir()359   MGetInlinedArgumentHole* mir() const {
360     return mir_->toGetInlinedArgumentHole();
361   }
362 };
363 
364 // Common code for LIR descended from MCall.
365 template <size_t Defs, size_t Operands, size_t Temps>
366 class LJSCallInstructionHelper
367     : public LCallInstructionHelper<Defs, Operands, Temps> {
368  protected:
LJSCallInstructionHelper(LNode::Opcode opcode)369   explicit LJSCallInstructionHelper(LNode::Opcode opcode)
370       : LCallInstructionHelper<Defs, Operands, Temps>(opcode) {}
371 
372  public:
argslot()373   uint32_t argslot() const {
374     if (JitStackValueAlignment > 1) {
375       return AlignBytes(mir()->numStackArgs(), JitStackValueAlignment);
376     }
377     return mir()->numStackArgs();
378   }
mir()379   MCall* mir() const { return this->mir_->toCall(); }
380 
hasSingleTarget()381   bool hasSingleTarget() const { return getSingleTarget() != nullptr; }
getSingleTarget()382   WrappedFunction* getSingleTarget() const { return mir()->getSingleTarget(); }
383 
384   // Does not include |this|.
numActualArgs()385   uint32_t numActualArgs() const { return mir()->numActualArgs(); }
386 
isConstructing()387   bool isConstructing() const { return mir()->isConstructing(); }
ignoresReturnValue()388   bool ignoresReturnValue() const { return mir()->ignoresReturnValue(); }
389 };
390 
391 // Generates a polymorphic callsite, wherein the function being called is
392 // unknown and anticipated to vary.
393 class LCallGeneric : public LJSCallInstructionHelper<BOX_PIECES, 1, 2> {
394  public:
LIR_HEADER(CallGeneric)395   LIR_HEADER(CallGeneric)
396 
397   LCallGeneric(const LAllocation& func, const LDefinition& nargsreg,
398                const LDefinition& tmpobjreg)
399       : LJSCallInstructionHelper(classOpcode) {
400     setOperand(0, func);
401     setTemp(0, nargsreg);
402     setTemp(1, tmpobjreg);
403   }
404 
getFunction()405   const LAllocation* getFunction() { return getOperand(0); }
getNargsReg()406   const LDefinition* getNargsReg() { return getTemp(0); }
getTempObject()407   const LDefinition* getTempObject() { return getTemp(1); }
408 };
409 
410 // Generates a hardcoded callsite for a known, non-native target.
411 class LCallKnown : public LJSCallInstructionHelper<BOX_PIECES, 1, 1> {
412  public:
LIR_HEADER(CallKnown)413   LIR_HEADER(CallKnown)
414 
415   LCallKnown(const LAllocation& func, const LDefinition& tmpobjreg)
416       : LJSCallInstructionHelper(classOpcode) {
417     setOperand(0, func);
418     setTemp(0, tmpobjreg);
419   }
420 
getFunction()421   const LAllocation* getFunction() { return getOperand(0); }
getTempObject()422   const LDefinition* getTempObject() { return getTemp(0); }
423 };
424 
425 // Generates a hardcoded callsite for a known, native target.
426 class LCallNative : public LJSCallInstructionHelper<BOX_PIECES, 0, 4> {
427  public:
LIR_HEADER(CallNative)428   LIR_HEADER(CallNative)
429 
430   LCallNative(const LDefinition& argContext, const LDefinition& argUintN,
431               const LDefinition& argVp, const LDefinition& tmpreg)
432       : LJSCallInstructionHelper(classOpcode) {
433     // Registers used for callWithABI().
434     setTemp(0, argContext);
435     setTemp(1, argUintN);
436     setTemp(2, argVp);
437 
438     // Temporary registers.
439     setTemp(3, tmpreg);
440   }
441 
getArgContextReg()442   const LDefinition* getArgContextReg() { return getTemp(0); }
getArgUintNReg()443   const LDefinition* getArgUintNReg() { return getTemp(1); }
getArgVpReg()444   const LDefinition* getArgVpReg() { return getTemp(2); }
getTempReg()445   const LDefinition* getTempReg() { return getTemp(3); }
446 };
447 
448 // Generates a hardcoded callsite for a known, DOM-native target.
449 class LCallDOMNative : public LJSCallInstructionHelper<BOX_PIECES, 0, 4> {
450  public:
LIR_HEADER(CallDOMNative)451   LIR_HEADER(CallDOMNative)
452 
453   LCallDOMNative(const LDefinition& argJSContext, const LDefinition& argObj,
454                  const LDefinition& argPrivate, const LDefinition& argArgs)
455       : LJSCallInstructionHelper(classOpcode) {
456     setTemp(0, argJSContext);
457     setTemp(1, argObj);
458     setTemp(2, argPrivate);
459     setTemp(3, argArgs);
460   }
461 
getArgJSContext()462   const LDefinition* getArgJSContext() { return getTemp(0); }
getArgObj()463   const LDefinition* getArgObj() { return getTemp(1); }
getArgPrivate()464   const LDefinition* getArgPrivate() { return getTemp(2); }
getArgArgs()465   const LDefinition* getArgArgs() { return getTemp(3); }
466 };
467 
468 class LUnreachable : public LControlInstructionHelper<0, 0, 0> {
469  public:
LIR_HEADER(Unreachable)470   LIR_HEADER(Unreachable)
471 
472   LUnreachable() : LControlInstructionHelper(classOpcode) {}
473 };
474 
475 class LUnreachableResultV : public LInstructionHelper<BOX_PIECES, 0, 0> {
476  public:
LIR_HEADER(UnreachableResultV)477   LIR_HEADER(UnreachableResultV)
478 
479   LUnreachableResultV() : LInstructionHelper(classOpcode) {}
480 };
481 
482 template <size_t defs, size_t ops>
483 class LDOMPropertyInstructionHelper
484     : public LCallInstructionHelper<defs, 1 + ops, 3> {
485  protected:
LDOMPropertyInstructionHelper(LNode::Opcode opcode,const LDefinition & JSContextReg,const LAllocation & ObjectReg,const LDefinition & PrivReg,const LDefinition & ValueReg)486   LDOMPropertyInstructionHelper(LNode::Opcode opcode,
487                                 const LDefinition& JSContextReg,
488                                 const LAllocation& ObjectReg,
489                                 const LDefinition& PrivReg,
490                                 const LDefinition& ValueReg)
491       : LCallInstructionHelper<defs, 1 + ops, 3>(opcode) {
492     this->setOperand(0, ObjectReg);
493     this->setTemp(0, JSContextReg);
494     this->setTemp(1, PrivReg);
495     this->setTemp(2, ValueReg);
496   }
497 
498  public:
getJSContextReg()499   const LDefinition* getJSContextReg() { return this->getTemp(0); }
getObjectReg()500   const LAllocation* getObjectReg() { return this->getOperand(0); }
getPrivReg()501   const LDefinition* getPrivReg() { return this->getTemp(1); }
getValueReg()502   const LDefinition* getValueReg() { return this->getTemp(2); }
503 };
504 
505 class LGetDOMProperty : public LDOMPropertyInstructionHelper<BOX_PIECES, 0> {
506  public:
LIR_HEADER(GetDOMProperty)507   LIR_HEADER(GetDOMProperty)
508 
509   LGetDOMProperty(const LDefinition& JSContextReg, const LAllocation& ObjectReg,
510                   const LDefinition& PrivReg, const LDefinition& ValueReg)
511       : LDOMPropertyInstructionHelper<BOX_PIECES, 0>(
512             classOpcode, JSContextReg, ObjectReg, PrivReg, ValueReg) {}
513 
mir()514   MGetDOMProperty* mir() const { return mir_->toGetDOMProperty(); }
515 };
516 
517 class LGetDOMMemberV : public LInstructionHelper<BOX_PIECES, 1, 0> {
518  public:
519   LIR_HEADER(GetDOMMemberV);
LGetDOMMemberV(const LAllocation & object)520   explicit LGetDOMMemberV(const LAllocation& object)
521       : LInstructionHelper(classOpcode) {
522     setOperand(0, object);
523   }
524 
object()525   const LAllocation* object() { return getOperand(0); }
526 
mir()527   MGetDOMMember* mir() const { return mir_->toGetDOMMember(); }
528 };
529 
530 class LSetDOMProperty : public LDOMPropertyInstructionHelper<0, BOX_PIECES> {
531  public:
LIR_HEADER(SetDOMProperty)532   LIR_HEADER(SetDOMProperty)
533 
534   LSetDOMProperty(const LDefinition& JSContextReg, const LAllocation& ObjectReg,
535                   const LBoxAllocation& value, const LDefinition& PrivReg,
536                   const LDefinition& ValueReg)
537       : LDOMPropertyInstructionHelper<0, BOX_PIECES>(
538             classOpcode, JSContextReg, ObjectReg, PrivReg, ValueReg) {
539     setBoxOperand(Value, value);
540   }
541 
542   static const size_t Value = 1;
543 
mir()544   MSetDOMProperty* mir() const { return mir_->toSetDOMProperty(); }
545 };
546 
547 // Generates a polymorphic callsite, wherein the function being called is
548 // unknown and anticipated to vary.
549 class LApplyArgsGeneric
550     : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 2, 2> {
551  public:
LIR_HEADER(ApplyArgsGeneric)552   LIR_HEADER(ApplyArgsGeneric)
553 
554   LApplyArgsGeneric(const LAllocation& func, const LAllocation& argc,
555                     const LBoxAllocation& thisv, const LDefinition& tmpobjreg,
556                     const LDefinition& tmpcopy)
557       : LCallInstructionHelper(classOpcode) {
558     setOperand(0, func);
559     setOperand(1, argc);
560     setBoxOperand(ThisIndex, thisv);
561     setTemp(0, tmpobjreg);
562     setTemp(1, tmpcopy);
563   }
564 
mir()565   MApplyArgs* mir() const { return mir_->toApplyArgs(); }
566 
hasSingleTarget()567   bool hasSingleTarget() const { return getSingleTarget() != nullptr; }
getSingleTarget()568   WrappedFunction* getSingleTarget() const { return mir()->getSingleTarget(); }
569 
getFunction()570   const LAllocation* getFunction() { return getOperand(0); }
getArgc()571   const LAllocation* getArgc() { return getOperand(1); }
572   static const size_t ThisIndex = 2;
573 
getTempObject()574   const LDefinition* getTempObject() { return getTemp(0); }
getTempStackCounter()575   const LDefinition* getTempStackCounter() { return getTemp(1); }
576 };
577 
578 class LApplyArgsObj
579     : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 2, 2> {
580  public:
LIR_HEADER(ApplyArgsObj)581   LIR_HEADER(ApplyArgsObj)
582 
583   LApplyArgsObj(const LAllocation& func, const LAllocation& argsObj,
584                 const LBoxAllocation& thisv, const LDefinition& tmpObjReg,
585                 const LDefinition& tmpCopy)
586       : LCallInstructionHelper(classOpcode) {
587     setOperand(0, func);
588     setOperand(1, argsObj);
589     setBoxOperand(ThisIndex, thisv);
590     setTemp(0, tmpObjReg);
591     setTemp(1, tmpCopy);
592   }
593 
mir()594   MApplyArgsObj* mir() const { return mir_->toApplyArgsObj(); }
595 
hasSingleTarget()596   bool hasSingleTarget() const { return getSingleTarget() != nullptr; }
getSingleTarget()597   WrappedFunction* getSingleTarget() const { return mir()->getSingleTarget(); }
598 
getFunction()599   const LAllocation* getFunction() { return getOperand(0); }
getArgsObj()600   const LAllocation* getArgsObj() { return getOperand(1); }
601   // All registers are calltemps. argc is mapped to the same register as
602   // ArgsObj. argc becomes live as ArgsObj is dying.
getArgc()603   const LAllocation* getArgc() { return getOperand(1); }
604   static const size_t ThisIndex = 2;
605 
getTempObject()606   const LDefinition* getTempObject() { return getTemp(0); }
getTempStackCounter()607   const LDefinition* getTempStackCounter() { return getTemp(1); }
608 };
609 
610 class LApplyArrayGeneric
611     : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 2, 2> {
612  public:
LIR_HEADER(ApplyArrayGeneric)613   LIR_HEADER(ApplyArrayGeneric)
614 
615   LApplyArrayGeneric(const LAllocation& func, const LAllocation& elements,
616                      const LBoxAllocation& thisv, const LDefinition& tmpobjreg,
617                      const LDefinition& tmpcopy)
618       : LCallInstructionHelper(classOpcode) {
619     setOperand(0, func);
620     setOperand(1, elements);
621     setBoxOperand(ThisIndex, thisv);
622     setTemp(0, tmpobjreg);
623     setTemp(1, tmpcopy);
624   }
625 
mir()626   MApplyArray* mir() const { return mir_->toApplyArray(); }
627 
hasSingleTarget()628   bool hasSingleTarget() const { return getSingleTarget() != nullptr; }
getSingleTarget()629   WrappedFunction* getSingleTarget() const { return mir()->getSingleTarget(); }
630 
getFunction()631   const LAllocation* getFunction() { return getOperand(0); }
getElements()632   const LAllocation* getElements() { return getOperand(1); }
633   // argc is mapped to the same register as elements: argc becomes
634   // live as elements is dying, all registers are calltemps.
getArgc()635   const LAllocation* getArgc() { return getOperand(1); }
636   static const size_t ThisIndex = 2;
637 
getTempObject()638   const LDefinition* getTempObject() { return getTemp(0); }
getTempStackCounter()639   const LDefinition* getTempStackCounter() { return getTemp(1); }
640 };
641 
642 class LConstructArgsGeneric
643     : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 3, 1> {
644  public:
LIR_HEADER(ConstructArgsGeneric)645   LIR_HEADER(ConstructArgsGeneric)
646 
647   LConstructArgsGeneric(const LAllocation& func, const LAllocation& argc,
648                         const LAllocation& newTarget,
649                         const LBoxAllocation& thisv,
650                         const LDefinition& tmpobjreg)
651       : LCallInstructionHelper(classOpcode) {
652     setOperand(0, func);
653     setOperand(1, argc);
654     setOperand(2, newTarget);
655     setBoxOperand(ThisIndex, thisv);
656     setTemp(0, tmpobjreg);
657   }
658 
mir()659   MConstructArgs* mir() const { return mir_->toConstructArgs(); }
660 
hasSingleTarget()661   bool hasSingleTarget() const { return getSingleTarget() != nullptr; }
getSingleTarget()662   WrappedFunction* getSingleTarget() const { return mir()->getSingleTarget(); }
663 
getFunction()664   const LAllocation* getFunction() { return getOperand(0); }
getArgc()665   const LAllocation* getArgc() { return getOperand(1); }
getNewTarget()666   const LAllocation* getNewTarget() { return getOperand(2); }
667 
668   static const size_t ThisIndex = 3;
669 
getTempObject()670   const LDefinition* getTempObject() { return getTemp(0); }
671 
672   // tempStackCounter is mapped to the same register as newTarget:
673   // tempStackCounter becomes live as newTarget is dying, all registers are
674   // calltemps.
getTempStackCounter()675   const LAllocation* getTempStackCounter() { return getOperand(2); }
676 };
677 
678 class LConstructArrayGeneric
679     : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 3, 1> {
680  public:
LIR_HEADER(ConstructArrayGeneric)681   LIR_HEADER(ConstructArrayGeneric)
682 
683   LConstructArrayGeneric(const LAllocation& func, const LAllocation& elements,
684                          const LAllocation& newTarget,
685                          const LBoxAllocation& thisv,
686                          const LDefinition& tmpobjreg)
687       : LCallInstructionHelper(classOpcode) {
688     setOperand(0, func);
689     setOperand(1, elements);
690     setOperand(2, newTarget);
691     setBoxOperand(ThisIndex, thisv);
692     setTemp(0, tmpobjreg);
693   }
694 
mir()695   MConstructArray* mir() const { return mir_->toConstructArray(); }
696 
hasSingleTarget()697   bool hasSingleTarget() const { return getSingleTarget() != nullptr; }
getSingleTarget()698   WrappedFunction* getSingleTarget() const { return mir()->getSingleTarget(); }
699 
getFunction()700   const LAllocation* getFunction() { return getOperand(0); }
getElements()701   const LAllocation* getElements() { return getOperand(1); }
getNewTarget()702   const LAllocation* getNewTarget() { return getOperand(2); }
703 
704   static const size_t ThisIndex = 3;
705 
getTempObject()706   const LDefinition* getTempObject() { return getTemp(0); }
707 
708   // argc is mapped to the same register as elements: argc becomes
709   // live as elements is dying, all registers are calltemps.
getArgc()710   const LAllocation* getArgc() { return getOperand(1); }
711 
712   // tempStackCounter is mapped to the same register as newTarget:
713   // tempStackCounter becomes live as newTarget is dying, all registers are
714   // calltemps.
getTempStackCounter()715   const LAllocation* getTempStackCounter() { return getOperand(2); }
716 };
717 
718 // Takes in either an integer or boolean input and tests it for truthiness.
719 class LTestIAndBranch : public LControlInstructionHelper<2, 1, 0> {
720  public:
LIR_HEADER(TestIAndBranch)721   LIR_HEADER(TestIAndBranch)
722 
723   LTestIAndBranch(const LAllocation& in, MBasicBlock* ifTrue,
724                   MBasicBlock* ifFalse)
725       : LControlInstructionHelper(classOpcode) {
726     setOperand(0, in);
727     setSuccessor(0, ifTrue);
728     setSuccessor(1, ifFalse);
729   }
730 
ifTrue()731   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()732   MBasicBlock* ifFalse() const { return getSuccessor(1); }
733 };
734 
735 // Takes in an int64 input and tests it for truthiness.
736 class LTestI64AndBranch : public LControlInstructionHelper<2, INT64_PIECES, 0> {
737  public:
LIR_HEADER(TestI64AndBranch)738   LIR_HEADER(TestI64AndBranch)
739 
740   LTestI64AndBranch(const LInt64Allocation& in, MBasicBlock* ifTrue,
741                     MBasicBlock* ifFalse)
742       : LControlInstructionHelper(classOpcode) {
743     setInt64Operand(0, in);
744     setSuccessor(0, ifTrue);
745     setSuccessor(1, ifFalse);
746   }
747 
ifTrue()748   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()749   MBasicBlock* ifFalse() const { return getSuccessor(1); }
750 };
751 
752 // Takes in a double input and tests it for truthiness.
753 class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0> {
754  public:
LIR_HEADER(TestDAndBranch)755   LIR_HEADER(TestDAndBranch)
756 
757   LTestDAndBranch(const LAllocation& in, MBasicBlock* ifTrue,
758                   MBasicBlock* ifFalse)
759       : LControlInstructionHelper(classOpcode) {
760     setOperand(0, in);
761     setSuccessor(0, ifTrue);
762     setSuccessor(1, ifFalse);
763   }
764 
ifTrue()765   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()766   MBasicBlock* ifFalse() const { return getSuccessor(1); }
767 };
768 
769 // Takes in a float32 input and tests it for truthiness.
770 class LTestFAndBranch : public LControlInstructionHelper<2, 1, 0> {
771  public:
LIR_HEADER(TestFAndBranch)772   LIR_HEADER(TestFAndBranch)
773 
774   LTestFAndBranch(const LAllocation& in, MBasicBlock* ifTrue,
775                   MBasicBlock* ifFalse)
776       : LControlInstructionHelper(classOpcode) {
777     setOperand(0, in);
778     setSuccessor(0, ifTrue);
779     setSuccessor(1, ifFalse);
780   }
781 
ifTrue()782   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()783   MBasicBlock* ifFalse() const { return getSuccessor(1); }
784 };
785 
786 // Takes in a bigint input and tests it for truthiness.
787 class LTestBIAndBranch : public LControlInstructionHelper<2, 1, 0> {
788  public:
LIR_HEADER(TestBIAndBranch)789   LIR_HEADER(TestBIAndBranch)
790 
791   LTestBIAndBranch(const LAllocation& in, MBasicBlock* ifTrue,
792                    MBasicBlock* ifFalse)
793       : LControlInstructionHelper(classOpcode) {
794     setOperand(0, in);
795     setSuccessor(0, ifTrue);
796     setSuccessor(1, ifFalse);
797   }
798 
ifTrue()799   MBasicBlock* ifTrue() { return getSuccessor(0); }
ifFalse()800   MBasicBlock* ifFalse() { return getSuccessor(1); }
801 };
802 
803 // Takes an object and tests it for truthiness.  An object is falsy iff it
804 // emulates |undefined|; see js::EmulatesUndefined.
805 class LTestOAndBranch : public LControlInstructionHelper<2, 1, 1> {
806  public:
LIR_HEADER(TestOAndBranch)807   LIR_HEADER(TestOAndBranch)
808 
809   LTestOAndBranch(const LAllocation& input, MBasicBlock* ifTruthy,
810                   MBasicBlock* ifFalsy, const LDefinition& temp)
811       : LControlInstructionHelper(classOpcode) {
812     setOperand(0, input);
813     setSuccessor(0, ifTruthy);
814     setSuccessor(1, ifFalsy);
815     setTemp(0, temp);
816   }
817 
temp()818   const LDefinition* temp() { return getTemp(0); }
819 
ifTruthy()820   MBasicBlock* ifTruthy() { return getSuccessor(0); }
ifFalsy()821   MBasicBlock* ifFalsy() { return getSuccessor(1); }
822 
mir()823   MTest* mir() { return mir_->toTest(); }
824 };
825 
826 // Takes in a boxed value and tests it for truthiness.
827 class LTestVAndBranch : public LControlInstructionHelper<2, BOX_PIECES, 3> {
828  public:
LIR_HEADER(TestVAndBranch)829   LIR_HEADER(TestVAndBranch)
830 
831   LTestVAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy,
832                   const LBoxAllocation& input, const LDefinition& temp0,
833                   const LDefinition& temp1, const LDefinition& temp2)
834       : LControlInstructionHelper(classOpcode) {
835     setSuccessor(0, ifTruthy);
836     setSuccessor(1, ifFalsy);
837     setBoxOperand(Input, input);
838     setTemp(0, temp0);
839     setTemp(1, temp1);
840     setTemp(2, temp2);
841   }
842 
843   static const size_t Input = 0;
844 
tempFloat()845   const LDefinition* tempFloat() { return getTemp(0); }
846 
temp1()847   const LDefinition* temp1() { return getTemp(1); }
848 
temp2()849   const LDefinition* temp2() { return getTemp(2); }
850 
ifTruthy()851   MBasicBlock* ifTruthy() { return getSuccessor(0); }
ifFalsy()852   MBasicBlock* ifFalsy() { return getSuccessor(1); }
853 
mir()854   MTest* mir() const { return mir_->toTest(); }
855 };
856 
857 // Compares two integral values of the same JS type, either integer or object.
858 // For objects, both operands are in registers.
859 class LCompare : public LInstructionHelper<1, 2, 0> {
860   JSOp jsop_;
861 
862  public:
LIR_HEADER(Compare)863   LIR_HEADER(Compare)
864   LCompare(JSOp jsop, const LAllocation& left, const LAllocation& right)
865       : LInstructionHelper(classOpcode), jsop_(jsop) {
866     setOperand(0, left);
867     setOperand(1, right);
868   }
869 
jsop()870   JSOp jsop() const { return jsop_; }
left()871   const LAllocation* left() { return getOperand(0); }
right()872   const LAllocation* right() { return getOperand(1); }
mir()873   MCompare* mir() { return mir_->toCompare(); }
extraName()874   const char* extraName() const { return CodeName(jsop_); }
875 };
876 
877 class LCompareI64 : public LInstructionHelper<1, 2 * INT64_PIECES, 0> {
878   JSOp jsop_;
879 
880  public:
881   LIR_HEADER(CompareI64)
882 
883   static const size_t Lhs = 0;
884   static const size_t Rhs = INT64_PIECES;
885 
LCompareI64(JSOp jsop,const LInt64Allocation & left,const LInt64Allocation & right)886   LCompareI64(JSOp jsop, const LInt64Allocation& left,
887               const LInt64Allocation& right)
888       : LInstructionHelper(classOpcode), jsop_(jsop) {
889     setInt64Operand(Lhs, left);
890     setInt64Operand(Rhs, right);
891   }
892 
jsop()893   JSOp jsop() const { return jsop_; }
mir()894   MCompare* mir() { return mir_->toCompare(); }
extraName()895   const char* extraName() const { return CodeName(jsop_); }
896 };
897 
898 class LCompareI64AndBranch
899     : public LControlInstructionHelper<2, 2 * INT64_PIECES, 0> {
900   MCompare* cmpMir_;
901   JSOp jsop_;
902 
903  public:
904   LIR_HEADER(CompareI64AndBranch)
905 
906   static const size_t Lhs = 0;
907   static const size_t Rhs = INT64_PIECES;
908 
LCompareI64AndBranch(MCompare * cmpMir,JSOp jsop,const LInt64Allocation & left,const LInt64Allocation & right,MBasicBlock * ifTrue,MBasicBlock * ifFalse)909   LCompareI64AndBranch(MCompare* cmpMir, JSOp jsop,
910                        const LInt64Allocation& left,
911                        const LInt64Allocation& right, MBasicBlock* ifTrue,
912                        MBasicBlock* ifFalse)
913       : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {
914     setInt64Operand(Lhs, left);
915     setInt64Operand(Rhs, right);
916     setSuccessor(0, ifTrue);
917     setSuccessor(1, ifFalse);
918   }
919 
jsop()920   JSOp jsop() const { return jsop_; }
ifTrue()921   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()922   MBasicBlock* ifFalse() const { return getSuccessor(1); }
mir()923   MTest* mir() const { return mir_->toTest(); }
cmpMir()924   MCompare* cmpMir() const { return cmpMir_; }
extraName()925   const char* extraName() const { return CodeName(jsop_); }
926 };
927 
928 // Compares two integral values of the same JS type, either integer or object.
929 // For objects, both operands are in registers.
930 class LCompareAndBranch : public LControlInstructionHelper<2, 2, 0> {
931   MCompare* cmpMir_;
932   JSOp jsop_;
933 
934  public:
LIR_HEADER(CompareAndBranch)935   LIR_HEADER(CompareAndBranch)
936   LCompareAndBranch(MCompare* cmpMir, JSOp jsop, const LAllocation& left,
937                     const LAllocation& right, MBasicBlock* ifTrue,
938                     MBasicBlock* ifFalse)
939       : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {
940     setOperand(0, left);
941     setOperand(1, right);
942     setSuccessor(0, ifTrue);
943     setSuccessor(1, ifFalse);
944   }
945 
jsop()946   JSOp jsop() const { return jsop_; }
ifTrue()947   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()948   MBasicBlock* ifFalse() const { return getSuccessor(1); }
left()949   const LAllocation* left() { return getOperand(0); }
right()950   const LAllocation* right() { return getOperand(1); }
mir()951   MTest* mir() const { return mir_->toTest(); }
cmpMir()952   MCompare* cmpMir() const { return cmpMir_; }
extraName()953   const char* extraName() const { return CodeName(jsop_); }
954 };
955 
956 class LCompareDAndBranch : public LControlInstructionHelper<2, 2, 0> {
957   MCompare* cmpMir_;
958 
959  public:
LIR_HEADER(CompareDAndBranch)960   LIR_HEADER(CompareDAndBranch)
961 
962   LCompareDAndBranch(MCompare* cmpMir, const LAllocation& left,
963                      const LAllocation& right, MBasicBlock* ifTrue,
964                      MBasicBlock* ifFalse)
965       : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {
966     setOperand(0, left);
967     setOperand(1, right);
968     setSuccessor(0, ifTrue);
969     setSuccessor(1, ifFalse);
970   }
971 
ifTrue()972   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()973   MBasicBlock* ifFalse() const { return getSuccessor(1); }
left()974   const LAllocation* left() { return getOperand(0); }
right()975   const LAllocation* right() { return getOperand(1); }
mir()976   MTest* mir() const { return mir_->toTest(); }
cmpMir()977   MCompare* cmpMir() const { return cmpMir_; }
978 };
979 
980 class LCompareFAndBranch : public LControlInstructionHelper<2, 2, 0> {
981   MCompare* cmpMir_;
982 
983  public:
LIR_HEADER(CompareFAndBranch)984   LIR_HEADER(CompareFAndBranch)
985   LCompareFAndBranch(MCompare* cmpMir, const LAllocation& left,
986                      const LAllocation& right, MBasicBlock* ifTrue,
987                      MBasicBlock* ifFalse)
988       : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {
989     setOperand(0, left);
990     setOperand(1, right);
991     setSuccessor(0, ifTrue);
992     setSuccessor(1, ifFalse);
993   }
994 
ifTrue()995   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()996   MBasicBlock* ifFalse() const { return getSuccessor(1); }
left()997   const LAllocation* left() { return getOperand(0); }
right()998   const LAllocation* right() { return getOperand(1); }
mir()999   MTest* mir() const { return mir_->toTest(); }
cmpMir()1000   MCompare* cmpMir() const { return cmpMir_; }
1001 };
1002 
1003 class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0> {
1004   // This denotes only a single-word AND on the target.  Hence `is64_` is
1005   // required to be `false` on a 32-bit target.
1006   bool is64_;
1007   Assembler::Condition cond_;
1008 
1009  public:
LIR_HEADER(BitAndAndBranch)1010   LIR_HEADER(BitAndAndBranch)
1011   LBitAndAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, bool is64,
1012                    Assembler::Condition cond = Assembler::NonZero)
1013       : LControlInstructionHelper(classOpcode), is64_(is64), cond_(cond) {
1014     setSuccessor(0, ifTrue);
1015     setSuccessor(1, ifFalse);
1016   }
1017 
ifTrue()1018   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1019   MBasicBlock* ifFalse() const { return getSuccessor(1); }
left()1020   const LAllocation* left() { return getOperand(0); }
right()1021   const LAllocation* right() { return getOperand(1); }
is64()1022   bool is64() const { return is64_; }
cond()1023   Assembler::Condition cond() const {
1024     MOZ_ASSERT(cond_ == Assembler::Zero || cond_ == Assembler::NonZero);
1025     return cond_;
1026   }
1027 };
1028 
1029 class LIsNullOrLikeUndefinedAndBranchV
1030     : public LControlInstructionHelper<2, BOX_PIECES, 2> {
1031   MCompare* cmpMir_;
1032 
1033  public:
LIR_HEADER(IsNullOrLikeUndefinedAndBranchV)1034   LIR_HEADER(IsNullOrLikeUndefinedAndBranchV)
1035 
1036   LIsNullOrLikeUndefinedAndBranchV(MCompare* cmpMir, MBasicBlock* ifTrue,
1037                                    MBasicBlock* ifFalse,
1038                                    const LBoxAllocation& value,
1039                                    const LDefinition& temp,
1040                                    const LDefinition& tempToUnbox)
1041       : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {
1042     setSuccessor(0, ifTrue);
1043     setSuccessor(1, ifFalse);
1044     setBoxOperand(Value, value);
1045     setTemp(0, temp);
1046     setTemp(1, tempToUnbox);
1047   }
1048 
1049   static const size_t Value = 0;
1050 
ifTrue()1051   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1052   MBasicBlock* ifFalse() const { return getSuccessor(1); }
mir()1053   MTest* mir() const { return mir_->toTest(); }
cmpMir()1054   MCompare* cmpMir() const { return cmpMir_; }
temp()1055   const LDefinition* temp() { return getTemp(0); }
tempToUnbox()1056   const LDefinition* tempToUnbox() { return getTemp(1); }
1057 };
1058 
1059 class LIsNullOrLikeUndefinedAndBranchT
1060     : public LControlInstructionHelper<2, 1, 1> {
1061   MCompare* cmpMir_;
1062 
1063  public:
LIR_HEADER(IsNullOrLikeUndefinedAndBranchT)1064   LIR_HEADER(IsNullOrLikeUndefinedAndBranchT)
1065 
1066   LIsNullOrLikeUndefinedAndBranchT(MCompare* cmpMir, const LAllocation& input,
1067                                    MBasicBlock* ifTrue, MBasicBlock* ifFalse,
1068                                    const LDefinition& temp)
1069       : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {
1070     setOperand(0, input);
1071     setSuccessor(0, ifTrue);
1072     setSuccessor(1, ifFalse);
1073     setTemp(0, temp);
1074   }
1075 
ifTrue()1076   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1077   MBasicBlock* ifFalse() const { return getSuccessor(1); }
mir()1078   MTest* mir() const { return mir_->toTest(); }
cmpMir()1079   MCompare* cmpMir() const { return cmpMir_; }
temp()1080   const LDefinition* temp() { return getTemp(0); }
1081 };
1082 
1083 // Bitwise not operation, takes a 32-bit integer as input and returning
1084 // a 32-bit integer result as an output.
1085 class LBitNotI : public LInstructionHelper<1, 1, 0> {
1086  public:
LIR_HEADER(BitNotI)1087   LIR_HEADER(BitNotI)
1088 
1089   LBitNotI() : LInstructionHelper(classOpcode) {}
1090 };
1091 
1092 class LBitNotI64 : public LInstructionHelper<INT64_PIECES, INT64_PIECES, 0> {
1093  public:
LIR_HEADER(BitNotI64)1094   LIR_HEADER(BitNotI64)
1095 
1096   LBitNotI64() : LInstructionHelper(classOpcode) {}
1097 };
1098 
1099 // Binary bitwise operation, taking two 32-bit integers as inputs and returning
1100 // a 32-bit integer result as an output.
1101 class LBitOpI : public LInstructionHelper<1, 2, 0> {
1102   JSOp op_;
1103 
1104  public:
LIR_HEADER(BitOpI)1105   LIR_HEADER(BitOpI)
1106 
1107   explicit LBitOpI(JSOp op) : LInstructionHelper(classOpcode), op_(op) {}
1108 
extraName()1109   const char* extraName() const {
1110     if (bitop() == JSOp::Ursh && mir_->toUrsh()->bailoutsDisabled()) {
1111       return "ursh:BailoutsDisabled";
1112     }
1113     return CodeName(op_);
1114   }
1115 
bitop()1116   JSOp bitop() const { return op_; }
1117 };
1118 
1119 class LBitOpI64 : public LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 0> {
1120   JSOp op_;
1121 
1122  public:
1123   LIR_HEADER(BitOpI64)
1124 
1125   static const size_t Lhs = 0;
1126   static const size_t Rhs = INT64_PIECES;
1127 
LBitOpI64(JSOp op)1128   explicit LBitOpI64(JSOp op) : LInstructionHelper(classOpcode), op_(op) {}
1129 
extraName()1130   const char* extraName() const { return CodeName(op_); }
1131 
bitop()1132   JSOp bitop() const { return op_; }
1133 };
1134 
1135 // Shift operation, taking two 32-bit integers as inputs and returning
1136 // a 32-bit integer result as an output.
1137 class LShiftI : public LBinaryMath<0> {
1138   JSOp op_;
1139 
1140  public:
LIR_HEADER(ShiftI)1141   LIR_HEADER(ShiftI)
1142 
1143   explicit LShiftI(JSOp op) : LBinaryMath(classOpcode), op_(op) {}
1144 
bitop()1145   JSOp bitop() { return op_; }
1146 
mir()1147   MInstruction* mir() { return mir_->toInstruction(); }
1148 
extraName()1149   const char* extraName() const { return CodeName(op_); }
1150 };
1151 
1152 class LShiftI64 : public LInstructionHelper<INT64_PIECES, INT64_PIECES + 1, 0> {
1153   JSOp op_;
1154 
1155  public:
LIR_HEADER(ShiftI64)1156   LIR_HEADER(ShiftI64)
1157 
1158   explicit LShiftI64(JSOp op) : LInstructionHelper(classOpcode), op_(op) {}
1159 
1160   static const size_t Lhs = 0;
1161   static const size_t Rhs = INT64_PIECES;
1162 
bitop()1163   JSOp bitop() { return op_; }
1164 
mir()1165   MInstruction* mir() { return mir_->toInstruction(); }
1166 
extraName()1167   const char* extraName() const { return CodeName(op_); }
1168 };
1169 
1170 class LSignExtendInt64
1171     : public LInstructionHelper<INT64_PIECES, INT64_PIECES, 0> {
1172  public:
LIR_HEADER(SignExtendInt64)1173   LIR_HEADER(SignExtendInt64)
1174 
1175   explicit LSignExtendInt64(const LInt64Allocation& input)
1176       : LInstructionHelper(classOpcode) {
1177     setInt64Operand(0, input);
1178   }
1179 
mir()1180   const MSignExtendInt64* mir() const { return mir_->toSignExtendInt64(); }
1181 
mode()1182   MSignExtendInt64::Mode mode() const { return mir()->mode(); }
1183 };
1184 
1185 class LUrshD : public LBinaryMath<1> {
1186  public:
LIR_HEADER(UrshD)1187   LIR_HEADER(UrshD)
1188 
1189   LUrshD(const LAllocation& lhs, const LAllocation& rhs,
1190          const LDefinition& temp)
1191       : LBinaryMath(classOpcode) {
1192     setOperand(0, lhs);
1193     setOperand(1, rhs);
1194     setTemp(0, temp);
1195   }
temp()1196   const LDefinition* temp() { return getTemp(0); }
1197 };
1198 
1199 // Returns from the function being compiled (not used in inlined frames). The
1200 // input must be a box.
1201 class LReturn : public LInstructionHelper<0, BOX_PIECES, 0> {
1202   bool isGenerator_;
1203 
1204  public:
LIR_HEADER(Return)1205   LIR_HEADER(Return)
1206 
1207   explicit LReturn(bool isGenerator)
1208       : LInstructionHelper(classOpcode), isGenerator_(isGenerator) {}
1209 
isGenerator()1210   bool isGenerator() { return isGenerator_; }
1211 };
1212 
1213 class LMinMaxBase : public LInstructionHelper<1, 2, 0> {
1214  protected:
LMinMaxBase(LNode::Opcode opcode,const LAllocation & first,const LAllocation & second)1215   LMinMaxBase(LNode::Opcode opcode, const LAllocation& first,
1216               const LAllocation& second)
1217       : LInstructionHelper(opcode) {
1218     setOperand(0, first);
1219     setOperand(1, second);
1220   }
1221 
1222  public:
first()1223   const LAllocation* first() { return this->getOperand(0); }
second()1224   const LAllocation* second() { return this->getOperand(1); }
output()1225   const LDefinition* output() { return this->getDef(0); }
mir()1226   MMinMax* mir() const { return mir_->toMinMax(); }
extraName()1227   const char* extraName() const { return mir()->isMax() ? "Max" : "Min"; }
1228 };
1229 
1230 class LMinMaxI : public LMinMaxBase {
1231  public:
LIR_HEADER(MinMaxI)1232   LIR_HEADER(MinMaxI)
1233   LMinMaxI(const LAllocation& first, const LAllocation& second)
1234       : LMinMaxBase(classOpcode, first, second) {}
1235 };
1236 
1237 class LMinMaxD : public LMinMaxBase {
1238  public:
LIR_HEADER(MinMaxD)1239   LIR_HEADER(MinMaxD)
1240   LMinMaxD(const LAllocation& first, const LAllocation& second)
1241       : LMinMaxBase(classOpcode, first, second) {}
1242 };
1243 
1244 class LMinMaxF : public LMinMaxBase {
1245  public:
LIR_HEADER(MinMaxF)1246   LIR_HEADER(MinMaxF)
1247   LMinMaxF(const LAllocation& first, const LAllocation& second)
1248       : LMinMaxBase(classOpcode, first, second) {}
1249 };
1250 
1251 class LMinMaxArrayI : public LInstructionHelper<1, 1, 3> {
1252  public:
1253   LIR_HEADER(MinMaxArrayI);
LMinMaxArrayI(const LAllocation & array,const LDefinition & temp0,const LDefinition & temp1,const LDefinition & temp2)1254   LMinMaxArrayI(const LAllocation& array, const LDefinition& temp0,
1255                 const LDefinition& temp1, const LDefinition& temp2)
1256       : LInstructionHelper(classOpcode) {
1257     setOperand(0, array);
1258     setTemp(0, temp0);
1259     setTemp(1, temp1);
1260     setTemp(2, temp2);
1261   }
1262 
array()1263   const LAllocation* array() { return getOperand(0); }
temp1()1264   const LDefinition* temp1() { return getTemp(0); }
temp2()1265   const LDefinition* temp2() { return getTemp(1); }
temp3()1266   const LDefinition* temp3() { return getTemp(2); }
1267 
isMax()1268   bool isMax() const { return mir_->toMinMaxArray()->isMax(); }
1269 };
1270 
1271 class LMinMaxArrayD : public LInstructionHelper<1, 1, 3> {
1272  public:
1273   LIR_HEADER(MinMaxArrayD);
LMinMaxArrayD(const LAllocation & array,const LDefinition & floatTemp,const LDefinition & temp1,const LDefinition & temp2)1274   LMinMaxArrayD(const LAllocation& array, const LDefinition& floatTemp,
1275                 const LDefinition& temp1, const LDefinition& temp2)
1276       : LInstructionHelper(classOpcode) {
1277     setOperand(0, array);
1278     setTemp(0, floatTemp);
1279     setTemp(1, temp1);
1280     setTemp(2, temp2);
1281   }
1282 
array()1283   const LAllocation* array() { return getOperand(0); }
floatTemp()1284   const LDefinition* floatTemp() { return getTemp(0); }
temp1()1285   const LDefinition* temp1() { return getTemp(1); }
temp2()1286   const LDefinition* temp2() { return getTemp(2); }
1287 
isMax()1288   bool isMax() const { return mir_->toMinMaxArray()->isMax(); }
1289 };
1290 
1291 // Copysign for doubles.
1292 class LCopySignD : public LInstructionHelper<1, 2, 2> {
1293  public:
LIR_HEADER(CopySignD)1294   LIR_HEADER(CopySignD)
1295   explicit LCopySignD() : LInstructionHelper(classOpcode) {}
1296 };
1297 
1298 // Copysign for float32.
1299 class LCopySignF : public LInstructionHelper<1, 2, 2> {
1300  public:
LIR_HEADER(CopySignF)1301   LIR_HEADER(CopySignF)
1302   explicit LCopySignF() : LInstructionHelper(classOpcode) {}
1303 };
1304 
1305 class LAtan2D : public LCallInstructionHelper<1, 2, 1> {
1306  public:
LIR_HEADER(Atan2D)1307   LIR_HEADER(Atan2D)
1308   LAtan2D(const LAllocation& y, const LAllocation& x, const LDefinition& temp)
1309       : LCallInstructionHelper(classOpcode) {
1310     setOperand(0, y);
1311     setOperand(1, x);
1312     setTemp(0, temp);
1313   }
1314 
y()1315   const LAllocation* y() { return getOperand(0); }
1316 
x()1317   const LAllocation* x() { return getOperand(1); }
1318 
temp()1319   const LDefinition* temp() { return getTemp(0); }
1320 
output()1321   const LDefinition* output() { return getDef(0); }
1322 };
1323 
1324 class LHypot : public LCallInstructionHelper<1, 4, 1> {
1325   uint32_t numOperands_;
1326 
1327  public:
LIR_HEADER(Hypot)1328   LIR_HEADER(Hypot)
1329   LHypot(const LAllocation& x, const LAllocation& y, const LDefinition& temp)
1330       : LCallInstructionHelper(classOpcode), numOperands_(2) {
1331     setOperand(0, x);
1332     setOperand(1, y);
1333     setTemp(0, temp);
1334   }
1335 
LHypot(const LAllocation & x,const LAllocation & y,const LAllocation & z,const LDefinition & temp)1336   LHypot(const LAllocation& x, const LAllocation& y, const LAllocation& z,
1337          const LDefinition& temp)
1338       : LCallInstructionHelper(classOpcode), numOperands_(3) {
1339     setOperand(0, x);
1340     setOperand(1, y);
1341     setOperand(2, z);
1342     setTemp(0, temp);
1343   }
1344 
LHypot(const LAllocation & x,const LAllocation & y,const LAllocation & z,const LAllocation & w,const LDefinition & temp)1345   LHypot(const LAllocation& x, const LAllocation& y, const LAllocation& z,
1346          const LAllocation& w, const LDefinition& temp)
1347       : LCallInstructionHelper(classOpcode), numOperands_(4) {
1348     setOperand(0, x);
1349     setOperand(1, y);
1350     setOperand(2, z);
1351     setOperand(3, w);
1352     setTemp(0, temp);
1353   }
1354 
numArgs()1355   uint32_t numArgs() const { return numOperands_; }
1356 
x()1357   const LAllocation* x() { return getOperand(0); }
1358 
y()1359   const LAllocation* y() { return getOperand(1); }
1360 
temp()1361   const LDefinition* temp() { return getTemp(0); }
1362 
output()1363   const LDefinition* output() { return getDef(0); }
1364 };
1365 
1366 class LMathFunctionD : public LCallInstructionHelper<1, 1, 1> {
1367  public:
LIR_HEADER(MathFunctionD)1368   LIR_HEADER(MathFunctionD)
1369   LMathFunctionD(const LAllocation& input, const LDefinition& temp)
1370       : LCallInstructionHelper(classOpcode) {
1371     setOperand(0, input);
1372     setTemp(0, temp);
1373   }
1374 
temp()1375   const LDefinition* temp() { return getTemp(0); }
mir()1376   MMathFunction* mir() const { return mir_->toMathFunction(); }
extraName()1377   const char* extraName() const {
1378     return MMathFunction::FunctionName(mir()->function());
1379   }
1380 };
1381 
1382 class LMathFunctionF : public LCallInstructionHelper<1, 1, 1> {
1383  public:
LIR_HEADER(MathFunctionF)1384   LIR_HEADER(MathFunctionF)
1385   LMathFunctionF(const LAllocation& input, const LDefinition& temp)
1386       : LCallInstructionHelper(classOpcode) {
1387     setOperand(0, input);
1388     setTemp(0, temp);
1389   }
1390 
temp()1391   const LDefinition* temp() { return getTemp(0); }
mir()1392   MMathFunction* mir() const { return mir_->toMathFunction(); }
extraName()1393   const char* extraName() const {
1394     return MMathFunction::FunctionName(mir()->function());
1395   }
1396 };
1397 
1398 // Adds two integers, returning an integer value.
1399 class LAddI : public LBinaryMath<0> {
1400   bool recoversInput_;
1401 
1402  public:
LIR_HEADER(AddI)1403   LIR_HEADER(AddI)
1404 
1405   LAddI() : LBinaryMath(classOpcode), recoversInput_(false) {}
1406 
extraName()1407   const char* extraName() const {
1408     return snapshot() ? "OverflowCheck" : nullptr;
1409   }
1410 
recoversInput()1411   bool recoversInput() const { return recoversInput_; }
setRecoversInput()1412   void setRecoversInput() { recoversInput_ = true; }
1413 
mir()1414   MAdd* mir() const { return mir_->toAdd(); }
1415 };
1416 
1417 class LAddI64 : public LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 0> {
1418  public:
LIR_HEADER(AddI64)1419   LIR_HEADER(AddI64)
1420 
1421   LAddI64() : LInstructionHelper(classOpcode) {}
1422 
1423   static const size_t Lhs = 0;
1424   static const size_t Rhs = INT64_PIECES;
1425 };
1426 
1427 // Subtracts two integers, returning an integer value.
1428 class LSubI : public LBinaryMath<0> {
1429   bool recoversInput_;
1430 
1431  public:
LIR_HEADER(SubI)1432   LIR_HEADER(SubI)
1433 
1434   LSubI() : LBinaryMath(classOpcode), recoversInput_(false) {}
1435 
extraName()1436   const char* extraName() const {
1437     return snapshot() ? "OverflowCheck" : nullptr;
1438   }
1439 
recoversInput()1440   bool recoversInput() const { return recoversInput_; }
setRecoversInput()1441   void setRecoversInput() { recoversInput_ = true; }
mir()1442   MSub* mir() const { return mir_->toSub(); }
1443 };
1444 
recoversInput()1445 inline bool LNode::recoversInput() const {
1446   switch (op()) {
1447     case Opcode::AddI:
1448       return toAddI()->recoversInput();
1449     case Opcode::SubI:
1450       return toSubI()->recoversInput();
1451     default:
1452       return false;
1453   }
1454 }
1455 
1456 class LSubI64 : public LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 0> {
1457  public:
1458   LIR_HEADER(SubI64)
1459 
1460   static const size_t Lhs = 0;
1461   static const size_t Rhs = INT64_PIECES;
1462 
LSubI64()1463   LSubI64() : LInstructionHelper(classOpcode) {}
1464 };
1465 
1466 class LMulI64 : public LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 1> {
1467  public:
LIR_HEADER(MulI64)1468   LIR_HEADER(MulI64)
1469 
1470   explicit LMulI64() : LInstructionHelper(classOpcode) {
1471     setTemp(0, LDefinition());
1472   }
1473 
temp()1474   const LDefinition* temp() { return getTemp(0); }
1475 
1476   static const size_t Lhs = 0;
1477   static const size_t Rhs = INT64_PIECES;
1478 };
1479 
1480 // Performs an add, sub, mul, or div on two double values.
1481 class LMathD : public LBinaryMath<0> {
1482   JSOp jsop_;
1483 
1484  public:
LIR_HEADER(MathD)1485   LIR_HEADER(MathD)
1486 
1487   explicit LMathD(JSOp jsop) : LBinaryMath(classOpcode), jsop_(jsop) {}
1488 
jsop()1489   JSOp jsop() const { return jsop_; }
1490 
extraName()1491   const char* extraName() const { return CodeName(jsop_); }
1492 };
1493 
1494 // Performs an add, sub, mul, or div on two double values.
1495 class LMathF : public LBinaryMath<0> {
1496   JSOp jsop_;
1497 
1498  public:
LIR_HEADER(MathF)1499   LIR_HEADER(MathF)
1500 
1501   explicit LMathF(JSOp jsop) : LBinaryMath(classOpcode), jsop_(jsop) {}
1502 
jsop()1503   JSOp jsop() const { return jsop_; }
1504 
extraName()1505   const char* extraName() const { return CodeName(jsop_); }
1506 };
1507 
1508 class LModD : public LBinaryMath<1> {
1509  public:
LIR_HEADER(ModD)1510   LIR_HEADER(ModD)
1511 
1512   LModD(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp)
1513       : LBinaryMath(classOpcode) {
1514     setOperand(0, lhs);
1515     setOperand(1, rhs);
1516     setTemp(0, temp);
1517     setIsCall();
1518   }
temp()1519   const LDefinition* temp() { return getTemp(0); }
mir()1520   MMod* mir() const { return mir_->toMod(); }
1521 };
1522 
1523 class LModPowTwoD : public LInstructionHelper<1, 1, 0> {
1524   const uint32_t divisor_;
1525 
1526  public:
LIR_HEADER(ModPowTwoD)1527   LIR_HEADER(ModPowTwoD)
1528 
1529   LModPowTwoD(const LAllocation& lhs, uint32_t divisor)
1530       : LInstructionHelper(classOpcode), divisor_(divisor) {
1531     setOperand(0, lhs);
1532   }
1533 
divisor()1534   uint32_t divisor() const { return divisor_; }
lhs()1535   const LAllocation* lhs() { return getOperand(0); }
mir()1536   MMod* mir() const { return mir_->toMod(); }
1537 };
1538 
1539 class LBigIntAdd : public LBinaryMath<2> {
1540  public:
LIR_HEADER(BigIntAdd)1541   LIR_HEADER(BigIntAdd)
1542 
1543   LBigIntAdd(const LAllocation& lhs, const LAllocation& rhs,
1544              const LDefinition& temp1, const LDefinition& temp2)
1545       : LBinaryMath(classOpcode) {
1546     setOperand(0, lhs);
1547     setOperand(1, rhs);
1548     setTemp(0, temp1);
1549     setTemp(1, temp2);
1550   }
1551 
temp1()1552   const LDefinition* temp1() { return getTemp(0); }
temp2()1553   const LDefinition* temp2() { return getTemp(1); }
1554 };
1555 
1556 class LBigIntSub : public LBinaryMath<2> {
1557  public:
LIR_HEADER(BigIntSub)1558   LIR_HEADER(BigIntSub)
1559 
1560   LBigIntSub(const LAllocation& lhs, const LAllocation& rhs,
1561              const LDefinition& temp1, const LDefinition& temp2)
1562       : LBinaryMath(classOpcode) {
1563     setOperand(0, lhs);
1564     setOperand(1, rhs);
1565     setTemp(0, temp1);
1566     setTemp(1, temp2);
1567   }
1568 
temp1()1569   const LDefinition* temp1() { return getTemp(0); }
temp2()1570   const LDefinition* temp2() { return getTemp(1); }
1571 };
1572 
1573 class LBigIntMul : public LBinaryMath<2> {
1574  public:
LIR_HEADER(BigIntMul)1575   LIR_HEADER(BigIntMul)
1576 
1577   LBigIntMul(const LAllocation& lhs, const LAllocation& rhs,
1578              const LDefinition& temp1, const LDefinition& temp2)
1579       : LBinaryMath(classOpcode) {
1580     setOperand(0, lhs);
1581     setOperand(1, rhs);
1582     setTemp(0, temp1);
1583     setTemp(1, temp2);
1584   }
1585 
temp1()1586   const LDefinition* temp1() { return getTemp(0); }
temp2()1587   const LDefinition* temp2() { return getTemp(1); }
1588 };
1589 
1590 class LBigIntDiv : public LBinaryMath<2> {
1591  public:
LIR_HEADER(BigIntDiv)1592   LIR_HEADER(BigIntDiv)
1593 
1594   LBigIntDiv(const LAllocation& lhs, const LAllocation& rhs,
1595              const LDefinition& temp1, const LDefinition& temp2)
1596       : LBinaryMath(classOpcode) {
1597     setOperand(0, lhs);
1598     setOperand(1, rhs);
1599     setTemp(0, temp1);
1600     setTemp(1, temp2);
1601   }
1602 
temp1()1603   const LDefinition* temp1() { return getTemp(0); }
temp2()1604   const LDefinition* temp2() { return getTemp(1); }
1605 
mir()1606   const MBigIntDiv* mir() const { return mirRaw()->toBigIntDiv(); }
1607 };
1608 
1609 class LBigIntMod : public LBinaryMath<2> {
1610  public:
LIR_HEADER(BigIntMod)1611   LIR_HEADER(BigIntMod)
1612 
1613   LBigIntMod(const LAllocation& lhs, const LAllocation& rhs,
1614              const LDefinition& temp1, const LDefinition& temp2)
1615       : LBinaryMath(classOpcode) {
1616     setOperand(0, lhs);
1617     setOperand(1, rhs);
1618     setTemp(0, temp1);
1619     setTemp(1, temp2);
1620   }
1621 
temp1()1622   const LDefinition* temp1() { return getTemp(0); }
temp2()1623   const LDefinition* temp2() { return getTemp(1); }
1624 
mir()1625   const MBigIntMod* mir() const { return mirRaw()->toBigIntMod(); }
1626 };
1627 
1628 class LBigIntPow : public LBinaryMath<2> {
1629  public:
LIR_HEADER(BigIntPow)1630   LIR_HEADER(BigIntPow)
1631 
1632   LBigIntPow(const LAllocation& lhs, const LAllocation& rhs,
1633              const LDefinition& temp1, const LDefinition& temp2)
1634       : LBinaryMath(classOpcode) {
1635     setOperand(0, lhs);
1636     setOperand(1, rhs);
1637     setTemp(0, temp1);
1638     setTemp(1, temp2);
1639   }
1640 
temp1()1641   const LDefinition* temp1() { return getTemp(0); }
temp2()1642   const LDefinition* temp2() { return getTemp(1); }
1643 
mir()1644   const MBigIntPow* mir() const { return mirRaw()->toBigIntPow(); }
1645 };
1646 
1647 class LBigIntBitAnd : public LBinaryMath<2> {
1648  public:
LIR_HEADER(BigIntBitAnd)1649   LIR_HEADER(BigIntBitAnd)
1650 
1651   LBigIntBitAnd(const LAllocation& lhs, const LAllocation& rhs,
1652                 const LDefinition& temp1, const LDefinition& temp2)
1653       : LBinaryMath(classOpcode) {
1654     setOperand(0, lhs);
1655     setOperand(1, rhs);
1656     setTemp(0, temp1);
1657     setTemp(1, temp2);
1658   }
1659 
temp1()1660   const LDefinition* temp1() { return getTemp(0); }
temp2()1661   const LDefinition* temp2() { return getTemp(1); }
1662 };
1663 
1664 class LBigIntBitOr : public LBinaryMath<2> {
1665  public:
LIR_HEADER(BigIntBitOr)1666   LIR_HEADER(BigIntBitOr)
1667 
1668   LBigIntBitOr(const LAllocation& lhs, const LAllocation& rhs,
1669                const LDefinition& temp1, const LDefinition& temp2)
1670       : LBinaryMath(classOpcode) {
1671     setOperand(0, lhs);
1672     setOperand(1, rhs);
1673     setTemp(0, temp1);
1674     setTemp(1, temp2);
1675   }
1676 
temp1()1677   const LDefinition* temp1() { return getTemp(0); }
temp2()1678   const LDefinition* temp2() { return getTemp(1); }
1679 };
1680 
1681 class LBigIntBitXor : public LBinaryMath<2> {
1682  public:
LIR_HEADER(BigIntBitXor)1683   LIR_HEADER(BigIntBitXor)
1684 
1685   LBigIntBitXor(const LAllocation& lhs, const LAllocation& rhs,
1686                 const LDefinition& temp1, const LDefinition& temp2)
1687       : LBinaryMath(classOpcode) {
1688     setOperand(0, lhs);
1689     setOperand(1, rhs);
1690     setTemp(0, temp1);
1691     setTemp(1, temp2);
1692   }
1693 
temp1()1694   const LDefinition* temp1() { return getTemp(0); }
temp2()1695   const LDefinition* temp2() { return getTemp(1); }
1696 };
1697 
1698 class LBigIntLsh : public LBinaryMath<3> {
1699  public:
LIR_HEADER(BigIntLsh)1700   LIR_HEADER(BigIntLsh)
1701 
1702   LBigIntLsh(const LAllocation& lhs, const LAllocation& rhs,
1703              const LDefinition& temp1, const LDefinition& temp2,
1704              const LDefinition& temp3)
1705       : LBinaryMath(classOpcode) {
1706     setOperand(0, lhs);
1707     setOperand(1, rhs);
1708     setTemp(0, temp1);
1709     setTemp(1, temp2);
1710     setTemp(2, temp3);
1711   }
1712 
temp1()1713   const LDefinition* temp1() { return getTemp(0); }
temp2()1714   const LDefinition* temp2() { return getTemp(1); }
temp3()1715   const LDefinition* temp3() { return getTemp(2); }
1716 };
1717 
1718 class LBigIntRsh : public LBinaryMath<3> {
1719  public:
LIR_HEADER(BigIntRsh)1720   LIR_HEADER(BigIntRsh)
1721 
1722   LBigIntRsh(const LAllocation& lhs, const LAllocation& rhs,
1723              const LDefinition& temp1, const LDefinition& temp2,
1724              const LDefinition& temp3)
1725       : LBinaryMath(classOpcode) {
1726     setOperand(0, lhs);
1727     setOperand(1, rhs);
1728     setTemp(0, temp1);
1729     setTemp(1, temp2);
1730     setTemp(2, temp3);
1731   }
1732 
temp1()1733   const LDefinition* temp1() { return getTemp(0); }
temp2()1734   const LDefinition* temp2() { return getTemp(1); }
temp3()1735   const LDefinition* temp3() { return getTemp(2); }
1736 };
1737 
1738 class LBigIntIncrement : public LUnaryMath<2> {
1739  public:
LIR_HEADER(BigIntIncrement)1740   LIR_HEADER(BigIntIncrement)
1741 
1742   LBigIntIncrement(const LAllocation& input, const LDefinition& temp1,
1743                    const LDefinition& temp2)
1744       : LUnaryMath(classOpcode) {
1745     setOperand(0, input);
1746     setTemp(0, temp1);
1747     setTemp(1, temp2);
1748   }
1749 
temp1()1750   const LDefinition* temp1() { return getTemp(0); }
temp2()1751   const LDefinition* temp2() { return getTemp(1); }
1752 };
1753 
1754 class LBigIntDecrement : public LUnaryMath<2> {
1755  public:
LIR_HEADER(BigIntDecrement)1756   LIR_HEADER(BigIntDecrement)
1757 
1758   LBigIntDecrement(const LAllocation& input, const LDefinition& temp1,
1759                    const LDefinition& temp2)
1760       : LUnaryMath(classOpcode) {
1761     setOperand(0, input);
1762     setTemp(0, temp1);
1763     setTemp(1, temp2);
1764   }
1765 
temp1()1766   const LDefinition* temp1() { return getTemp(0); }
temp2()1767   const LDefinition* temp2() { return getTemp(1); }
1768 };
1769 
1770 class LBigIntNegate : public LUnaryMath<1> {
1771  public:
LIR_HEADER(BigIntNegate)1772   LIR_HEADER(BigIntNegate)
1773 
1774   LBigIntNegate(const LAllocation& input, const LDefinition& temp)
1775       : LUnaryMath(classOpcode) {
1776     setOperand(0, input);
1777     setTemp(0, temp);
1778   }
1779 
temp()1780   const LDefinition* temp() { return getTemp(0); }
1781 };
1782 
1783 class LBigIntBitNot : public LUnaryMath<2> {
1784  public:
LIR_HEADER(BigIntBitNot)1785   LIR_HEADER(BigIntBitNot)
1786 
1787   LBigIntBitNot(const LAllocation& input, const LDefinition& temp1,
1788                 const LDefinition& temp2)
1789       : LUnaryMath(classOpcode) {
1790     setOperand(0, input);
1791     setTemp(0, temp1);
1792     setTemp(1, temp2);
1793   }
1794 
temp1()1795   const LDefinition* temp1() { return getTemp(0); }
temp2()1796   const LDefinition* temp2() { return getTemp(1); }
1797 };
1798 
1799 // Convert a value to an int32.
1800 //   Input: components of a Value
1801 //   Output: 32-bit integer
1802 //   Bailout: undefined, string, object, or non-int32 double
1803 //   Temps: one float register, one GP register
1804 //
1805 // This instruction requires a temporary float register.
1806 class LValueToInt32 : public LInstructionHelper<1, BOX_PIECES, 2> {
1807  public:
1808   enum Mode { NORMAL, TRUNCATE, TRUNCATE_NOWRAP };
1809 
1810  private:
1811   Mode mode_;
1812 
1813  public:
LIR_HEADER(ValueToInt32)1814   LIR_HEADER(ValueToInt32)
1815 
1816   LValueToInt32(const LBoxAllocation& input, const LDefinition& temp0,
1817                 const LDefinition& temp1, Mode mode)
1818       : LInstructionHelper(classOpcode), mode_(mode) {
1819     setBoxOperand(Input, input);
1820     setTemp(0, temp0);
1821     setTemp(1, temp1);
1822   }
1823 
extraName()1824   const char* extraName() const {
1825     return mode() == NORMAL     ? "Normal"
1826            : mode() == TRUNCATE ? "Truncate"
1827                                 : "TruncateNoWrap";
1828   }
1829 
1830   static const size_t Input = 0;
1831 
mode()1832   Mode mode() const { return mode_; }
tempFloat()1833   const LDefinition* tempFloat() { return getTemp(0); }
temp()1834   const LDefinition* temp() { return getTemp(1); }
mirNormal()1835   MToNumberInt32* mirNormal() const {
1836     MOZ_ASSERT(mode_ == NORMAL);
1837     return mir_->toToNumberInt32();
1838   }
mirTruncate()1839   MTruncateToInt32* mirTruncate() const {
1840     MOZ_ASSERT(mode_ == TRUNCATE);
1841     return mir_->toTruncateToInt32();
1842   }
mirTruncateNoWrap()1843   MToIntegerInt32* mirTruncateNoWrap() const {
1844     MOZ_ASSERT(mode_ == TRUNCATE_NOWRAP);
1845     return mir_->toToIntegerInt32();
1846   }
mir()1847   MInstruction* mir() const { return mir_->toInstruction(); }
1848 };
1849 
1850 // Double raised to a half power.
1851 class LPowHalfD : public LInstructionHelper<1, 1, 0> {
1852  public:
1853   LIR_HEADER(PowHalfD);
LPowHalfD(const LAllocation & input)1854   explicit LPowHalfD(const LAllocation& input)
1855       : LInstructionHelper(classOpcode) {
1856     setOperand(0, input);
1857   }
1858 
input()1859   const LAllocation* input() { return getOperand(0); }
output()1860   const LDefinition* output() { return getDef(0); }
mir()1861   MPowHalf* mir() const { return mir_->toPowHalf(); }
1862 };
1863 
1864 // Passed the BaselineFrame address in the OsrFrameReg via the IonOsrTempData
1865 // populated by PrepareOsrTempData.
1866 //
1867 // Forwards this object to the LOsrValues for Value materialization.
1868 class LOsrEntry : public LInstructionHelper<1, 0, 1> {
1869  protected:
1870   Label label_;
1871   uint32_t frameDepth_;
1872 
1873  public:
LIR_HEADER(OsrEntry)1874   LIR_HEADER(OsrEntry)
1875 
1876   explicit LOsrEntry(const LDefinition& temp)
1877       : LInstructionHelper(classOpcode), frameDepth_(0) {
1878     setTemp(0, temp);
1879   }
1880 
setFrameDepth(uint32_t depth)1881   void setFrameDepth(uint32_t depth) { frameDepth_ = depth; }
getFrameDepth()1882   uint32_t getFrameDepth() { return frameDepth_; }
label()1883   Label* label() { return &label_; }
temp()1884   const LDefinition* temp() { return getTemp(0); }
1885 };
1886 
1887 // Bailout if index + minimum < 0 or index + maximum >= length.
1888 class LBoundsCheckRange : public LInstructionHelper<0, 2, 1> {
1889  public:
LIR_HEADER(BoundsCheckRange)1890   LIR_HEADER(BoundsCheckRange)
1891 
1892   LBoundsCheckRange(const LAllocation& index, const LAllocation& length,
1893                     const LDefinition& temp)
1894       : LInstructionHelper(classOpcode) {
1895     setOperand(0, index);
1896     setOperand(1, length);
1897     setTemp(0, temp);
1898   }
mir()1899   const MBoundsCheck* mir() const { return mir_->toBoundsCheck(); }
index()1900   const LAllocation* index() { return getOperand(0); }
length()1901   const LAllocation* length() { return getOperand(1); }
1902 };
1903 
1904 // Load a value from a dense array's elements vector. Bail out if it's the hole
1905 // value.
1906 class LLoadElementV : public LInstructionHelper<BOX_PIECES, 2, 0> {
1907  public:
LIR_HEADER(LoadElementV)1908   LIR_HEADER(LoadElementV)
1909 
1910   LLoadElementV(const LAllocation& elements, const LAllocation& index)
1911       : LInstructionHelper(classOpcode) {
1912     setOperand(0, elements);
1913     setOperand(1, index);
1914   }
1915 
mir()1916   const MLoadElement* mir() const { return mir_->toLoadElement(); }
elements()1917   const LAllocation* elements() { return getOperand(0); }
index()1918   const LAllocation* index() { return getOperand(1); }
1919 };
1920 
1921 // Load a value from an array's elements vector, loading |undefined| if we hit a
1922 // hole. Bail out if we get a negative index.
1923 class LLoadElementHole : public LInstructionHelper<BOX_PIECES, 3, 0> {
1924  public:
LIR_HEADER(LoadElementHole)1925   LIR_HEADER(LoadElementHole)
1926 
1927   LLoadElementHole(const LAllocation& elements, const LAllocation& index,
1928                    const LAllocation& initLength)
1929       : LInstructionHelper(classOpcode) {
1930     setOperand(0, elements);
1931     setOperand(1, index);
1932     setOperand(2, initLength);
1933   }
1934 
mir()1935   const MLoadElementHole* mir() const { return mir_->toLoadElementHole(); }
elements()1936   const LAllocation* elements() { return getOperand(0); }
index()1937   const LAllocation* index() { return getOperand(1); }
initLength()1938   const LAllocation* initLength() { return getOperand(2); }
1939 };
1940 
1941 // Store a boxed value to a dense array's element vector.
1942 class LStoreElementV : public LInstructionHelper<0, 2 + BOX_PIECES, 0> {
1943  public:
LIR_HEADER(StoreElementV)1944   LIR_HEADER(StoreElementV)
1945 
1946   LStoreElementV(const LAllocation& elements, const LAllocation& index,
1947                  const LBoxAllocation& value)
1948       : LInstructionHelper(classOpcode) {
1949     setOperand(0, elements);
1950     setOperand(1, index);
1951     setBoxOperand(Value, value);
1952   }
1953 
extraName()1954   const char* extraName() const {
1955     return mir()->needsHoleCheck() ? "HoleCheck" : nullptr;
1956   }
1957 
1958   static const size_t Value = 2;
1959 
mir()1960   const MStoreElement* mir() const { return mir_->toStoreElement(); }
elements()1961   const LAllocation* elements() { return getOperand(0); }
index()1962   const LAllocation* index() { return getOperand(1); }
1963 };
1964 
1965 // Store a typed value to a dense array's elements vector. Compared to
1966 // LStoreElementV, this instruction can store doubles and constants directly,
1967 // and does not store the type tag if the array is monomorphic and known to
1968 // be packed.
1969 class LStoreElementT : public LInstructionHelper<0, 3, 0> {
1970  public:
LIR_HEADER(StoreElementT)1971   LIR_HEADER(StoreElementT)
1972 
1973   LStoreElementT(const LAllocation& elements, const LAllocation& index,
1974                  const LAllocation& value)
1975       : LInstructionHelper(classOpcode) {
1976     setOperand(0, elements);
1977     setOperand(1, index);
1978     setOperand(2, value);
1979   }
1980 
extraName()1981   const char* extraName() const {
1982     return mir()->needsHoleCheck() ? "HoleCheck" : nullptr;
1983   }
1984 
mir()1985   const MStoreElement* mir() const { return mir_->toStoreElement(); }
elements()1986   const LAllocation* elements() { return getOperand(0); }
index()1987   const LAllocation* index() { return getOperand(1); }
value()1988   const LAllocation* value() { return getOperand(2); }
1989 };
1990 
1991 class LArrayPopShift : public LInstructionHelper<BOX_PIECES, 1, 2> {
1992  public:
LIR_HEADER(ArrayPopShift)1993   LIR_HEADER(ArrayPopShift)
1994 
1995   LArrayPopShift(const LAllocation& object, const LDefinition& temp0,
1996                  const LDefinition& temp1)
1997       : LInstructionHelper(classOpcode) {
1998     setOperand(0, object);
1999     setTemp(0, temp0);
2000     setTemp(1, temp1);
2001   }
2002 
extraName()2003   const char* extraName() const {
2004     return mir()->mode() == MArrayPopShift::Pop ? "Pop" : "Shift";
2005   }
2006 
mir()2007   const MArrayPopShift* mir() const { return mir_->toArrayPopShift(); }
object()2008   const LAllocation* object() { return getOperand(0); }
temp0()2009   const LDefinition* temp0() { return getTemp(0); }
temp1()2010   const LDefinition* temp1() { return getTemp(1); }
2011 };
2012 
2013 class LLoadUnboxedBigInt : public LInstructionHelper<1, 2, 1 + INT64_PIECES> {
2014  public:
LIR_HEADER(LoadUnboxedBigInt)2015   LIR_HEADER(LoadUnboxedBigInt)
2016 
2017   LLoadUnboxedBigInt(const LAllocation& elements, const LAllocation& index,
2018                      const LDefinition& temp, const LInt64Definition& temp64)
2019       : LInstructionHelper(classOpcode) {
2020     setOperand(0, elements);
2021     setOperand(1, index);
2022     setTemp(0, temp);
2023     setInt64Temp(1, temp64);
2024   }
mir()2025   const MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); }
elements()2026   const LAllocation* elements() { return getOperand(0); }
index()2027   const LAllocation* index() { return getOperand(1); }
temp()2028   const LDefinition* temp() { return getTemp(0); }
temp64()2029   const LInt64Definition temp64() { return getInt64Temp(1); }
2030 };
2031 
2032 class LLoadDataViewElement : public LInstructionHelper<1, 3, 1 + INT64_PIECES> {
2033  public:
LIR_HEADER(LoadDataViewElement)2034   LIR_HEADER(LoadDataViewElement)
2035 
2036   LLoadDataViewElement(const LAllocation& elements, const LAllocation& index,
2037                        const LAllocation& littleEndian, const LDefinition& temp,
2038                        const LInt64Definition& temp64)
2039       : LInstructionHelper(classOpcode) {
2040     setOperand(0, elements);
2041     setOperand(1, index);
2042     setOperand(2, littleEndian);
2043     setTemp(0, temp);
2044     setInt64Temp(1, temp64);
2045   }
mir()2046   const MLoadDataViewElement* mir() const {
2047     return mir_->toLoadDataViewElement();
2048   }
elements()2049   const LAllocation* elements() { return getOperand(0); }
index()2050   const LAllocation* index() { return getOperand(1); }
littleEndian()2051   const LAllocation* littleEndian() { return getOperand(2); }
temp()2052   const LDefinition* temp() { return getTemp(0); }
temp64()2053   const LInt64Definition temp64() { return getInt64Temp(1); }
2054 };
2055 
2056 class LLoadTypedArrayElementHoleBigInt
2057     : public LInstructionHelper<BOX_PIECES, 2, 1 + INT64_PIECES> {
2058  public:
LIR_HEADER(LoadTypedArrayElementHoleBigInt)2059   LIR_HEADER(LoadTypedArrayElementHoleBigInt)
2060 
2061   LLoadTypedArrayElementHoleBigInt(const LAllocation& object,
2062                                    const LAllocation& index,
2063                                    const LDefinition& temp,
2064                                    const LInt64Definition& temp64)
2065       : LInstructionHelper(classOpcode) {
2066     setOperand(0, object);
2067     setOperand(1, index);
2068     setTemp(0, temp);
2069     setInt64Temp(1, temp64);
2070   }
mir()2071   const MLoadTypedArrayElementHole* mir() const {
2072     return mir_->toLoadTypedArrayElementHole();
2073   }
object()2074   const LAllocation* object() { return getOperand(0); }
index()2075   const LAllocation* index() { return getOperand(1); }
temp()2076   const LDefinition* temp() { return getTemp(0); }
temp64()2077   const LInt64Definition temp64() { return getInt64Temp(1); }
2078 };
2079 
2080 class LStoreUnboxedBigInt : public LInstructionHelper<0, 3, INT64_PIECES> {
2081  public:
LIR_HEADER(StoreUnboxedBigInt)2082   LIR_HEADER(StoreUnboxedBigInt)
2083 
2084   LStoreUnboxedBigInt(const LAllocation& elements, const LAllocation& index,
2085                       const LAllocation& value, const LInt64Definition& temp)
2086       : LInstructionHelper(classOpcode) {
2087     setOperand(0, elements);
2088     setOperand(1, index);
2089     setOperand(2, value);
2090     setInt64Temp(0, temp);
2091   }
2092 
mir()2093   const MStoreUnboxedScalar* mir() const {
2094     return mir_->toStoreUnboxedScalar();
2095   }
elements()2096   const LAllocation* elements() { return getOperand(0); }
index()2097   const LAllocation* index() { return getOperand(1); }
value()2098   const LAllocation* value() { return getOperand(2); }
temp()2099   LInt64Definition temp() { return getInt64Temp(0); }
2100 };
2101 
2102 class LStoreDataViewElement
2103     : public LInstructionHelper<0, 4, 1 + INT64_PIECES> {
2104  public:
LIR_HEADER(StoreDataViewElement)2105   LIR_HEADER(StoreDataViewElement)
2106 
2107   LStoreDataViewElement(const LAllocation& elements, const LAllocation& index,
2108                         const LAllocation& value,
2109                         const LAllocation& littleEndian,
2110                         const LDefinition& temp, const LInt64Definition& temp64)
2111       : LInstructionHelper(classOpcode) {
2112     setOperand(0, elements);
2113     setOperand(1, index);
2114     setOperand(2, value);
2115     setOperand(3, littleEndian);
2116     setTemp(0, temp);
2117     setInt64Temp(1, temp64);
2118   }
2119 
mir()2120   const MStoreDataViewElement* mir() const {
2121     return mir_->toStoreDataViewElement();
2122   }
elements()2123   const LAllocation* elements() { return getOperand(0); }
index()2124   const LAllocation* index() { return getOperand(1); }
value()2125   const LAllocation* value() { return getOperand(2); }
littleEndian()2126   const LAllocation* littleEndian() { return getOperand(3); }
temp()2127   const LDefinition* temp() { return getTemp(0); }
temp64()2128   const LInt64Definition temp64() { return getInt64Temp(1); }
2129 };
2130 
2131 class LStoreTypedArrayElementHoleBigInt
2132     : public LInstructionHelper<0, 4, INT64_PIECES> {
2133  public:
LIR_HEADER(StoreTypedArrayElementHoleBigInt)2134   LIR_HEADER(StoreTypedArrayElementHoleBigInt)
2135 
2136   LStoreTypedArrayElementHoleBigInt(const LAllocation& elements,
2137                                     const LAllocation& length,
2138                                     const LAllocation& index,
2139                                     const LAllocation& value,
2140                                     const LInt64Definition& temp)
2141       : LInstructionHelper(classOpcode) {
2142     setOperand(0, elements);
2143     setOperand(1, length);
2144     setOperand(2, index);
2145     setOperand(3, value);
2146     setInt64Temp(0, temp);
2147   }
2148 
mir()2149   const MStoreTypedArrayElementHole* mir() const {
2150     return mir_->toStoreTypedArrayElementHole();
2151   }
elements()2152   const LAllocation* elements() { return getOperand(0); }
length()2153   const LAllocation* length() { return getOperand(1); }
index()2154   const LAllocation* index() { return getOperand(2); }
value()2155   const LAllocation* value() { return getOperand(3); }
temp()2156   LInt64Definition temp() { return getInt64Temp(0); }
2157 };
2158 
2159 class LCompareExchangeTypedArrayElement : public LInstructionHelper<1, 4, 4> {
2160  public:
LIR_HEADER(CompareExchangeTypedArrayElement)2161   LIR_HEADER(CompareExchangeTypedArrayElement)
2162 
2163   // ARM, ARM64, x86, x64
2164   LCompareExchangeTypedArrayElement(const LAllocation& elements,
2165                                     const LAllocation& index,
2166                                     const LAllocation& oldval,
2167                                     const LAllocation& newval,
2168                                     const LDefinition& temp)
2169       : LInstructionHelper(classOpcode) {
2170     setOperand(0, elements);
2171     setOperand(1, index);
2172     setOperand(2, oldval);
2173     setOperand(3, newval);
2174     setTemp(0, temp);
2175   }
2176   // MIPS32, MIPS64
LCompareExchangeTypedArrayElement(const LAllocation & elements,const LAllocation & index,const LAllocation & oldval,const LAllocation & newval,const LDefinition & temp,const LDefinition & valueTemp,const LDefinition & offsetTemp,const LDefinition & maskTemp)2177   LCompareExchangeTypedArrayElement(
2178       const LAllocation& elements, const LAllocation& index,
2179       const LAllocation& oldval, const LAllocation& newval,
2180       const LDefinition& temp, const LDefinition& valueTemp,
2181       const LDefinition& offsetTemp, const LDefinition& maskTemp)
2182       : LInstructionHelper(classOpcode) {
2183     setOperand(0, elements);
2184     setOperand(1, index);
2185     setOperand(2, oldval);
2186     setOperand(3, newval);
2187     setTemp(0, temp);
2188     setTemp(1, valueTemp);
2189     setTemp(2, offsetTemp);
2190     setTemp(3, maskTemp);
2191   }
2192 
elements()2193   const LAllocation* elements() { return getOperand(0); }
index()2194   const LAllocation* index() { return getOperand(1); }
oldval()2195   const LAllocation* oldval() { return getOperand(2); }
newval()2196   const LAllocation* newval() { return getOperand(3); }
temp()2197   const LDefinition* temp() { return getTemp(0); }
2198 
2199   // Temp that may be used on LL/SC platforms for extract/insert bits of word.
valueTemp()2200   const LDefinition* valueTemp() { return getTemp(1); }
offsetTemp()2201   const LDefinition* offsetTemp() { return getTemp(2); }
maskTemp()2202   const LDefinition* maskTemp() { return getTemp(3); }
2203 
mir()2204   const MCompareExchangeTypedArrayElement* mir() const {
2205     return mir_->toCompareExchangeTypedArrayElement();
2206   }
2207 };
2208 
2209 class LAtomicExchangeTypedArrayElement : public LInstructionHelper<1, 3, 4> {
2210  public:
LIR_HEADER(AtomicExchangeTypedArrayElement)2211   LIR_HEADER(AtomicExchangeTypedArrayElement)
2212 
2213   // ARM, ARM64, x86, x64
2214   LAtomicExchangeTypedArrayElement(const LAllocation& elements,
2215                                    const LAllocation& index,
2216                                    const LAllocation& value,
2217                                    const LDefinition& temp)
2218       : LInstructionHelper(classOpcode) {
2219     setOperand(0, elements);
2220     setOperand(1, index);
2221     setOperand(2, value);
2222     setTemp(0, temp);
2223   }
2224   // MIPS32, MIPS64
LAtomicExchangeTypedArrayElement(const LAllocation & elements,const LAllocation & index,const LAllocation & value,const LDefinition & temp,const LDefinition & valueTemp,const LDefinition & offsetTemp,const LDefinition & maskTemp)2225   LAtomicExchangeTypedArrayElement(const LAllocation& elements,
2226                                    const LAllocation& index,
2227                                    const LAllocation& value,
2228                                    const LDefinition& temp,
2229                                    const LDefinition& valueTemp,
2230                                    const LDefinition& offsetTemp,
2231                                    const LDefinition& maskTemp)
2232       : LInstructionHelper(classOpcode) {
2233     setOperand(0, elements);
2234     setOperand(1, index);
2235     setOperand(2, value);
2236     setTemp(0, temp);
2237     setTemp(1, valueTemp);
2238     setTemp(2, offsetTemp);
2239     setTemp(3, maskTemp);
2240   }
2241 
elements()2242   const LAllocation* elements() { return getOperand(0); }
index()2243   const LAllocation* index() { return getOperand(1); }
value()2244   const LAllocation* value() { return getOperand(2); }
temp()2245   const LDefinition* temp() { return getTemp(0); }
2246 
2247   // Temp that may be used on LL/SC platforms for extract/insert bits of word.
valueTemp()2248   const LDefinition* valueTemp() { return getTemp(1); }
offsetTemp()2249   const LDefinition* offsetTemp() { return getTemp(2); }
maskTemp()2250   const LDefinition* maskTemp() { return getTemp(3); }
2251 
mir()2252   const MAtomicExchangeTypedArrayElement* mir() const {
2253     return mir_->toAtomicExchangeTypedArrayElement();
2254   }
2255 };
2256 
2257 class LAtomicTypedArrayElementBinop : public LInstructionHelper<1, 3, 5> {
2258  public:
2259   LIR_HEADER(AtomicTypedArrayElementBinop)
2260 
2261   static const int32_t valueOp = 2;
2262 
2263   // ARM, ARM64, x86, x64
LAtomicTypedArrayElementBinop(const LAllocation & elements,const LAllocation & index,const LAllocation & value,const LDefinition & temp1,const LDefinition & temp2)2264   LAtomicTypedArrayElementBinop(const LAllocation& elements,
2265                                 const LAllocation& index,
2266                                 const LAllocation& value,
2267                                 const LDefinition& temp1,
2268                                 const LDefinition& temp2)
2269       : LInstructionHelper(classOpcode) {
2270     setOperand(0, elements);
2271     setOperand(1, index);
2272     setOperand(2, value);
2273     setTemp(0, temp1);
2274     setTemp(1, temp2);
2275   }
2276   // MIPS32, MIPS64
LAtomicTypedArrayElementBinop(const LAllocation & elements,const LAllocation & index,const LAllocation & value,const LDefinition & temp2,const LDefinition & valueTemp,const LDefinition & offsetTemp,const LDefinition & maskTemp)2277   LAtomicTypedArrayElementBinop(const LAllocation& elements,
2278                                 const LAllocation& index,
2279                                 const LAllocation& value,
2280                                 const LDefinition& temp2,
2281                                 const LDefinition& valueTemp,
2282                                 const LDefinition& offsetTemp,
2283                                 const LDefinition& maskTemp)
2284       : LInstructionHelper(classOpcode) {
2285     setOperand(0, elements);
2286     setOperand(1, index);
2287     setOperand(2, value);
2288     setTemp(0, LDefinition::BogusTemp());
2289     setTemp(1, temp2);
2290     setTemp(2, valueTemp);
2291     setTemp(3, offsetTemp);
2292     setTemp(4, maskTemp);
2293   }
2294 
elements()2295   const LAllocation* elements() { return getOperand(0); }
index()2296   const LAllocation* index() { return getOperand(1); }
value()2297   const LAllocation* value() {
2298     MOZ_ASSERT(valueOp == 2);
2299     return getOperand(2);
2300   }
temp1()2301   const LDefinition* temp1() { return getTemp(0); }
temp2()2302   const LDefinition* temp2() { return getTemp(1); }
2303 
2304   // Temp that may be used on LL/SC platforms for extract/insert bits of word.
valueTemp()2305   const LDefinition* valueTemp() { return getTemp(2); }
offsetTemp()2306   const LDefinition* offsetTemp() { return getTemp(3); }
maskTemp()2307   const LDefinition* maskTemp() { return getTemp(4); }
2308 
mir()2309   const MAtomicTypedArrayElementBinop* mir() const {
2310     return mir_->toAtomicTypedArrayElementBinop();
2311   }
2312 };
2313 
2314 // Atomic binary operation where the result is discarded.
2315 class LAtomicTypedArrayElementBinopForEffect
2316     : public LInstructionHelper<0, 3, 4> {
2317  public:
LIR_HEADER(AtomicTypedArrayElementBinopForEffect)2318   LIR_HEADER(AtomicTypedArrayElementBinopForEffect)
2319 
2320   // ARM, ARM64, x86, x64
2321   LAtomicTypedArrayElementBinopForEffect(
2322       const LAllocation& elements, const LAllocation& index,
2323       const LAllocation& value,
2324       const LDefinition& flagTemp = LDefinition::BogusTemp())
2325       : LInstructionHelper(classOpcode) {
2326     setOperand(0, elements);
2327     setOperand(1, index);
2328     setOperand(2, value);
2329     setTemp(0, flagTemp);
2330   }
2331   // MIPS32, MIPS64
LAtomicTypedArrayElementBinopForEffect(const LAllocation & elements,const LAllocation & index,const LAllocation & value,const LDefinition & valueTemp,const LDefinition & offsetTemp,const LDefinition & maskTemp)2332   LAtomicTypedArrayElementBinopForEffect(const LAllocation& elements,
2333                                          const LAllocation& index,
2334                                          const LAllocation& value,
2335                                          const LDefinition& valueTemp,
2336                                          const LDefinition& offsetTemp,
2337                                          const LDefinition& maskTemp)
2338       : LInstructionHelper(classOpcode) {
2339     setOperand(0, elements);
2340     setOperand(1, index);
2341     setOperand(2, value);
2342     setTemp(0, LDefinition::BogusTemp());
2343     setTemp(1, valueTemp);
2344     setTemp(2, offsetTemp);
2345     setTemp(3, maskTemp);
2346   }
2347 
elements()2348   const LAllocation* elements() { return getOperand(0); }
index()2349   const LAllocation* index() { return getOperand(1); }
value()2350   const LAllocation* value() { return getOperand(2); }
2351 
2352   // Temp that may be used on LL/SC platforms for the flag result of the store.
flagTemp()2353   const LDefinition* flagTemp() { return getTemp(0); }
2354   // Temp that may be used on LL/SC platforms for extract/insert bits of word.
valueTemp()2355   const LDefinition* valueTemp() { return getTemp(1); }
offsetTemp()2356   const LDefinition* offsetTemp() { return getTemp(2); }
maskTemp()2357   const LDefinition* maskTemp() { return getTemp(3); }
2358 
mir()2359   const MAtomicTypedArrayElementBinop* mir() const {
2360     return mir_->toAtomicTypedArrayElementBinop();
2361   }
2362 };
2363 
2364 class LAtomicLoad64 : public LInstructionHelper<1, 2, 1 + INT64_PIECES> {
2365  public:
LIR_HEADER(AtomicLoad64)2366   LIR_HEADER(AtomicLoad64)
2367 
2368   LAtomicLoad64(const LAllocation& elements, const LAllocation& index,
2369                 const LDefinition& temp, const LInt64Definition& temp64)
2370       : LInstructionHelper(classOpcode) {
2371     setOperand(0, elements);
2372     setOperand(1, index);
2373     setTemp(0, temp);
2374     setInt64Temp(1, temp64);
2375   }
mir()2376   const MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); }
elements()2377   const LAllocation* elements() { return getOperand(0); }
index()2378   const LAllocation* index() { return getOperand(1); }
temp()2379   const LDefinition* temp() { return getTemp(0); }
temp64()2380   LInt64Definition temp64() { return getInt64Temp(1); }
2381 };
2382 
2383 class LAtomicStore64 : public LInstructionHelper<0, 3, 2 * INT64_PIECES + 1> {
2384  public:
LIR_HEADER(AtomicStore64)2385   LIR_HEADER(AtomicStore64)
2386 
2387   // x64, ARM64
2388   LAtomicStore64(const LAllocation& elements, const LAllocation& index,
2389                  const LAllocation& value, const LInt64Definition& temp1)
2390       : LInstructionHelper(classOpcode) {
2391     setOperand(0, elements);
2392     setOperand(1, index);
2393     setOperand(2, value);
2394     setInt64Temp(0, temp1);
2395     setInt64Temp(INT64_PIECES, LInt64Definition::BogusTemp());
2396     setTemp(2 * INT64_PIECES, LDefinition::BogusTemp());
2397   }
2398 
2399   // ARM32
LAtomicStore64(const LAllocation & elements,const LAllocation & index,const LAllocation & value,const LInt64Definition & temp1,const LInt64Definition & temp2)2400   LAtomicStore64(const LAllocation& elements, const LAllocation& index,
2401                  const LAllocation& value, const LInt64Definition& temp1,
2402                  const LInt64Definition& temp2)
2403       : LInstructionHelper(classOpcode) {
2404     setOperand(0, elements);
2405     setOperand(1, index);
2406     setOperand(2, value);
2407     setInt64Temp(0, temp1);
2408     setInt64Temp(INT64_PIECES, temp2);
2409     setTemp(2 * INT64_PIECES, LDefinition::BogusTemp());
2410   }
2411 
2412   // x86
LAtomicStore64(const LAllocation & elements,const LAllocation & index,const LAllocation & value,const LInt64Definition & temp1,const LDefinition & tempLow)2413   LAtomicStore64(const LAllocation& elements, const LAllocation& index,
2414                  const LAllocation& value, const LInt64Definition& temp1,
2415                  const LDefinition& tempLow)
2416       : LInstructionHelper(classOpcode) {
2417     setOperand(0, elements);
2418     setOperand(1, index);
2419     setOperand(2, value);
2420     setInt64Temp(0, temp1);
2421     setInt64Temp(INT64_PIECES, LInt64Definition::BogusTemp());
2422     setTemp(2 * INT64_PIECES, tempLow);
2423   }
2424 
mir()2425   const MStoreUnboxedScalar* mir() const {
2426     return mir_->toStoreUnboxedScalar();
2427   }
elements()2428   const LAllocation* elements() { return getOperand(0); }
index()2429   const LAllocation* index() { return getOperand(1); }
value()2430   const LAllocation* value() { return getOperand(2); }
temp1()2431   LInt64Definition temp1() { return getInt64Temp(0); }
temp2()2432   LInt64Definition temp2() { return getInt64Temp(INT64_PIECES); }
tempLow()2433   const LDefinition* tempLow() { return getTemp(2 * INT64_PIECES); }
2434 };
2435 
2436 class LCompareExchangeTypedArrayElement64
2437     : public LInstructionHelper<1, 4, 3 * INT64_PIECES + 1> {
2438  public:
LIR_HEADER(CompareExchangeTypedArrayElement64)2439   LIR_HEADER(CompareExchangeTypedArrayElement64)
2440 
2441   // x64, ARM64
2442   LCompareExchangeTypedArrayElement64(const LAllocation& elements,
2443                                       const LAllocation& index,
2444                                       const LAllocation& oldval,
2445                                       const LAllocation& newval,
2446                                       const LInt64Definition& temp1,
2447                                       const LInt64Definition& temp2)
2448       : LInstructionHelper(classOpcode) {
2449     setOperand(0, elements);
2450     setOperand(1, index);
2451     setOperand(2, oldval);
2452     setOperand(3, newval);
2453     setInt64Temp(0, temp1);
2454     setInt64Temp(INT64_PIECES, temp2);
2455     setInt64Temp(2 * INT64_PIECES, LInt64Definition::BogusTemp());
2456     setTemp(3 * INT64_PIECES, LDefinition::BogusTemp());
2457   }
2458 
2459   // x86
LCompareExchangeTypedArrayElement64(const LAllocation & elements,const LAllocation & index,const LAllocation & oldval,const LAllocation & newval,const LDefinition & tempLow)2460   LCompareExchangeTypedArrayElement64(const LAllocation& elements,
2461                                       const LAllocation& index,
2462                                       const LAllocation& oldval,
2463                                       const LAllocation& newval,
2464                                       const LDefinition& tempLow)
2465       : LInstructionHelper(classOpcode) {
2466     setOperand(0, elements);
2467     setOperand(1, index);
2468     setOperand(2, oldval);
2469     setOperand(3, newval);
2470     setInt64Temp(0, LInt64Definition::BogusTemp());
2471     setInt64Temp(INT64_PIECES, LInt64Definition::BogusTemp());
2472     setInt64Temp(2 * INT64_PIECES, LInt64Definition::BogusTemp());
2473     setTemp(3 * INT64_PIECES, tempLow);
2474   }
2475 
2476   // ARM
LCompareExchangeTypedArrayElement64(const LAllocation & elements,const LAllocation & index,const LAllocation & oldval,const LAllocation & newval,const LInt64Definition & temp1,const LInt64Definition & temp2,const LInt64Definition & temp3)2477   LCompareExchangeTypedArrayElement64(const LAllocation& elements,
2478                                       const LAllocation& index,
2479                                       const LAllocation& oldval,
2480                                       const LAllocation& newval,
2481                                       const LInt64Definition& temp1,
2482                                       const LInt64Definition& temp2,
2483                                       const LInt64Definition& temp3)
2484       : LInstructionHelper(classOpcode) {
2485     setOperand(0, elements);
2486     setOperand(1, index);
2487     setOperand(2, oldval);
2488     setOperand(3, newval);
2489     setInt64Temp(0, temp1);
2490     setInt64Temp(INT64_PIECES, temp2);
2491     setInt64Temp(2 * INT64_PIECES, temp3);
2492     setTemp(3 * INT64_PIECES, LDefinition::BogusTemp());
2493   }
2494 
mir()2495   const MCompareExchangeTypedArrayElement* mir() const {
2496     return mir_->toCompareExchangeTypedArrayElement();
2497   }
elements()2498   const LAllocation* elements() { return getOperand(0); }
index()2499   const LAllocation* index() { return getOperand(1); }
oldval()2500   const LAllocation* oldval() { return getOperand(2); }
newval()2501   const LAllocation* newval() { return getOperand(3); }
temp1()2502   LInt64Definition temp1() { return getInt64Temp(0); }
temp2()2503   LInt64Definition temp2() { return getInt64Temp(INT64_PIECES); }
temp3()2504   LInt64Definition temp3() { return getInt64Temp(2 * INT64_PIECES); }
tempLow()2505   const LDefinition* tempLow() { return getTemp(3 * INT64_PIECES); }
2506 };
2507 
2508 class LAtomicExchangeTypedArrayElement64
2509     : public LInstructionHelper<1, 3, INT64_PIECES + 1> {
2510  public:
LIR_HEADER(AtomicExchangeTypedArrayElement64)2511   LIR_HEADER(AtomicExchangeTypedArrayElement64)
2512 
2513   // ARM, ARM64, x64
2514   LAtomicExchangeTypedArrayElement64(const LAllocation& elements,
2515                                      const LAllocation& index,
2516                                      const LAllocation& value,
2517                                      const LInt64Definition& temp1,
2518                                      const LDefinition& temp2)
2519       : LInstructionHelper(classOpcode) {
2520     setOperand(0, elements);
2521     setOperand(1, index);
2522     setOperand(2, value);
2523     setInt64Temp(0, temp1);
2524     setTemp(INT64_PIECES, temp2);
2525   }
2526 
2527   // x86
LAtomicExchangeTypedArrayElement64(const LAllocation & elements,const LAllocation & index,const LAllocation & value,const LInt64Definition & temp)2528   LAtomicExchangeTypedArrayElement64(const LAllocation& elements,
2529                                      const LAllocation& index,
2530                                      const LAllocation& value,
2531                                      const LInt64Definition& temp)
2532       : LInstructionHelper(classOpcode) {
2533     setOperand(0, elements);
2534     setOperand(1, index);
2535     setOperand(2, value);
2536     setInt64Temp(0, temp);
2537     setTemp(INT64_PIECES, LDefinition::BogusTemp());
2538   }
2539 
elements()2540   const LAllocation* elements() { return getOperand(0); }
index()2541   const LAllocation* index() { return getOperand(1); }
value()2542   const LAllocation* value() { return getOperand(2); }
temp1()2543   LInt64Definition temp1() { return getInt64Temp(0); }
temp2()2544   const LDefinition* temp2() { return getTemp(INT64_PIECES); }
2545 
mir()2546   const MAtomicExchangeTypedArrayElement* mir() const {
2547     return mir_->toAtomicExchangeTypedArrayElement();
2548   }
2549 };
2550 
2551 class LAtomicTypedArrayElementBinop64
2552     : public LInstructionHelper<1, 3, 3 * INT64_PIECES> {
2553  public:
LIR_HEADER(AtomicTypedArrayElementBinop64)2554   LIR_HEADER(AtomicTypedArrayElementBinop64)
2555 
2556   // x86
2557   LAtomicTypedArrayElementBinop64(const LAllocation& elements,
2558                                   const LAllocation& index,
2559                                   const LAllocation& value,
2560                                   const LInt64Definition& temp1)
2561       : LInstructionHelper(classOpcode) {
2562     setOperand(0, elements);
2563     setOperand(1, index);
2564     setOperand(2, value);
2565     setInt64Temp(0, temp1);
2566     setInt64Temp(INT64_PIECES, LInt64Definition::BogusTemp());
2567     setInt64Temp(2 * INT64_PIECES, LInt64Definition::BogusTemp());
2568   }
2569 
2570   // ARM64, x64
LAtomicTypedArrayElementBinop64(const LAllocation & elements,const LAllocation & index,const LAllocation & value,const LInt64Definition & temp1,const LInt64Definition & temp2)2571   LAtomicTypedArrayElementBinop64(const LAllocation& elements,
2572                                   const LAllocation& index,
2573                                   const LAllocation& value,
2574                                   const LInt64Definition& temp1,
2575                                   const LInt64Definition& temp2)
2576       : LInstructionHelper(classOpcode) {
2577     setOperand(0, elements);
2578     setOperand(1, index);
2579     setOperand(2, value);
2580     setInt64Temp(0, temp1);
2581     setInt64Temp(INT64_PIECES, temp2);
2582     setInt64Temp(2 * INT64_PIECES, LInt64Definition::BogusTemp());
2583   }
2584 
2585   // ARM
LAtomicTypedArrayElementBinop64(const LAllocation & elements,const LAllocation & index,const LAllocation & value,const LInt64Definition & temp1,const LInt64Definition & temp2,const LInt64Definition & temp3)2586   LAtomicTypedArrayElementBinop64(const LAllocation& elements,
2587                                   const LAllocation& index,
2588                                   const LAllocation& value,
2589                                   const LInt64Definition& temp1,
2590                                   const LInt64Definition& temp2,
2591                                   const LInt64Definition& temp3)
2592       : LInstructionHelper(classOpcode) {
2593     setOperand(0, elements);
2594     setOperand(1, index);
2595     setOperand(2, value);
2596     setInt64Temp(0, temp1);
2597     setInt64Temp(INT64_PIECES, temp2);
2598     setInt64Temp(2 * INT64_PIECES, temp3);
2599   }
2600 
elements()2601   const LAllocation* elements() { return getOperand(0); }
index()2602   const LAllocation* index() { return getOperand(1); }
value()2603   const LAllocation* value() { return getOperand(2); }
temp1()2604   LInt64Definition temp1() { return getInt64Temp(0); }
temp2()2605   LInt64Definition temp2() { return getInt64Temp(INT64_PIECES); }
temp3()2606   LInt64Definition temp3() { return getInt64Temp(2 * INT64_PIECES); }
2607 
mir()2608   const MAtomicTypedArrayElementBinop* mir() const {
2609     return mir_->toAtomicTypedArrayElementBinop();
2610   }
2611 };
2612 
2613 // Atomic binary operation where the result is discarded.
2614 class LAtomicTypedArrayElementBinopForEffect64
2615     : public LInstructionHelper<0, 3, 2 * INT64_PIECES + 1> {
2616  public:
LIR_HEADER(AtomicTypedArrayElementBinopForEffect64)2617   LIR_HEADER(AtomicTypedArrayElementBinopForEffect64)
2618 
2619   // x86
2620   LAtomicTypedArrayElementBinopForEffect64(const LAllocation& elements,
2621                                            const LAllocation& index,
2622                                            const LAllocation& value,
2623                                            const LInt64Definition& temp,
2624                                            const LDefinition& tempLow)
2625       : LInstructionHelper(classOpcode) {
2626     setOperand(0, elements);
2627     setOperand(1, index);
2628     setOperand(2, value);
2629     setInt64Temp(0, temp);
2630     setInt64Temp(INT64_PIECES, LInt64Definition::BogusTemp());
2631     setTemp(2 * INT64_PIECES, tempLow);
2632   }
2633 
2634   // x64
LAtomicTypedArrayElementBinopForEffect64(const LAllocation & elements,const LAllocation & index,const LAllocation & value,const LInt64Definition & temp)2635   LAtomicTypedArrayElementBinopForEffect64(const LAllocation& elements,
2636                                            const LAllocation& index,
2637                                            const LAllocation& value,
2638                                            const LInt64Definition& temp)
2639       : LInstructionHelper(classOpcode) {
2640     setOperand(0, elements);
2641     setOperand(1, index);
2642     setOperand(2, value);
2643     setInt64Temp(0, temp);
2644     setInt64Temp(INT64_PIECES, LInt64Definition::BogusTemp());
2645     setTemp(2 * INT64_PIECES, LDefinition::BogusTemp());
2646   }
2647 
2648   // ARM64
LAtomicTypedArrayElementBinopForEffect64(const LAllocation & elements,const LAllocation & index,const LAllocation & value,const LInt64Definition & temp1,const LInt64Definition & temp2)2649   LAtomicTypedArrayElementBinopForEffect64(const LAllocation& elements,
2650                                            const LAllocation& index,
2651                                            const LAllocation& value,
2652                                            const LInt64Definition& temp1,
2653                                            const LInt64Definition& temp2)
2654       : LInstructionHelper(classOpcode) {
2655     setOperand(0, elements);
2656     setOperand(1, index);
2657     setOperand(2, value);
2658     setInt64Temp(0, temp1);
2659     setInt64Temp(INT64_PIECES, temp2);
2660     setTemp(2 * INT64_PIECES, LDefinition::BogusTemp());
2661   }
2662 
elements()2663   const LAllocation* elements() { return getOperand(0); }
index()2664   const LAllocation* index() { return getOperand(1); }
value()2665   const LAllocation* value() { return getOperand(2); }
temp1()2666   LInt64Definition temp1() { return getInt64Temp(0); }
temp2()2667   LInt64Definition temp2() { return getInt64Temp(INT64_PIECES); }
tempLow()2668   const LDefinition* tempLow() { return getTemp(2 * INT64_PIECES); }
2669 
mir()2670   const MAtomicTypedArrayElementBinop* mir() const {
2671     return mir_->toAtomicTypedArrayElementBinop();
2672   }
2673 };
2674 
2675 class LIsNoIterAndBranch : public LControlInstructionHelper<2, BOX_PIECES, 0> {
2676  public:
LIR_HEADER(IsNoIterAndBranch)2677   LIR_HEADER(IsNoIterAndBranch)
2678 
2679   LIsNoIterAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse,
2680                      const LBoxAllocation& input)
2681       : LControlInstructionHelper(classOpcode) {
2682     setSuccessor(0, ifTrue);
2683     setSuccessor(1, ifFalse);
2684     setBoxOperand(Input, input);
2685   }
2686 
2687   static const size_t Input = 0;
2688 
ifTrue()2689   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()2690   MBasicBlock* ifFalse() const { return getSuccessor(1); }
2691 };
2692 
2693 class LInstanceOfCache : public LInstructionHelper<1, BOX_PIECES + 1, 0> {
2694  public:
LIR_HEADER(InstanceOfCache)2695   LIR_HEADER(InstanceOfCache)
2696   LInstanceOfCache(const LBoxAllocation& lhs, const LAllocation& rhs)
2697       : LInstructionHelper(classOpcode) {
2698     setBoxOperand(LHS, lhs);
2699     setOperand(RHS, rhs);
2700   }
2701 
output()2702   const LDefinition* output() { return this->getDef(0); }
rhs()2703   const LAllocation* rhs() { return getOperand(RHS); }
2704 
2705   static const size_t LHS = 0;
2706   static const size_t RHS = BOX_PIECES;
2707 };
2708 
2709 class LIsObjectAndBranch : public LControlInstructionHelper<2, BOX_PIECES, 0> {
2710  public:
LIR_HEADER(IsObjectAndBranch)2711   LIR_HEADER(IsObjectAndBranch)
2712 
2713   LIsObjectAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse,
2714                      const LBoxAllocation& input)
2715       : LControlInstructionHelper(classOpcode) {
2716     setSuccessor(0, ifTrue);
2717     setSuccessor(1, ifFalse);
2718     setBoxOperand(Input, input);
2719   }
2720 
2721   static const size_t Input = 0;
2722 
ifTrue()2723   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()2724   MBasicBlock* ifFalse() const { return getSuccessor(1); }
2725 };
2726 
2727 class LIsNullOrUndefinedAndBranch
2728     : public LControlInstructionHelper<2, BOX_PIECES, 0> {
2729   MIsNullOrUndefined* isNullOrUndefined_;
2730 
2731  public:
2732   LIR_HEADER(IsNullOrUndefinedAndBranch)
2733   static const size_t Input = 0;
2734 
LIsNullOrUndefinedAndBranch(MIsNullOrUndefined * isNullOrUndefined,MBasicBlock * ifTrue,MBasicBlock * ifFalse,const LBoxAllocation & input)2735   LIsNullOrUndefinedAndBranch(MIsNullOrUndefined* isNullOrUndefined,
2736                               MBasicBlock* ifTrue, MBasicBlock* ifFalse,
2737                               const LBoxAllocation& input)
2738       : LControlInstructionHelper(classOpcode),
2739         isNullOrUndefined_(isNullOrUndefined) {
2740     setSuccessor(0, ifTrue);
2741     setSuccessor(1, ifFalse);
2742     setBoxOperand(Input, input);
2743   }
2744 
ifTrue()2745   MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()2746   MBasicBlock* ifFalse() const { return getSuccessor(1); }
2747 
isNullOrUndefinedMir()2748   MIsNullOrUndefined* isNullOrUndefinedMir() const {
2749     return isNullOrUndefined_;
2750   }
2751 };
2752 
2753 template <size_t Defs, size_t Ops>
2754 class LWasmSelectBase : public LInstructionHelper<Defs, Ops, 0> {
2755   typedef LInstructionHelper<Defs, Ops, 0> Base;
2756 
2757  protected:
LWasmSelectBase(LNode::Opcode opcode)2758   explicit LWasmSelectBase(LNode::Opcode opcode) : Base(opcode) {}
2759 
2760  public:
mir()2761   MWasmSelect* mir() const { return Base::mir_->toWasmSelect(); }
2762 };
2763 
2764 class LWasmSelect : public LWasmSelectBase<1, 3> {
2765  public:
2766   LIR_HEADER(WasmSelect);
2767 
2768   static const size_t TrueExprIndex = 0;
2769   static const size_t FalseExprIndex = 1;
2770   static const size_t CondIndex = 2;
2771 
LWasmSelect(const LAllocation & trueExpr,const LAllocation & falseExpr,const LAllocation & cond)2772   LWasmSelect(const LAllocation& trueExpr, const LAllocation& falseExpr,
2773               const LAllocation& cond)
2774       : LWasmSelectBase(classOpcode) {
2775     setOperand(TrueExprIndex, trueExpr);
2776     setOperand(FalseExprIndex, falseExpr);
2777     setOperand(CondIndex, cond);
2778   }
2779 
trueExpr()2780   const LAllocation* trueExpr() { return getOperand(TrueExprIndex); }
falseExpr()2781   const LAllocation* falseExpr() { return getOperand(FalseExprIndex); }
condExpr()2782   const LAllocation* condExpr() { return getOperand(CondIndex); }
2783 };
2784 
2785 class LWasmSelectI64
2786     : public LWasmSelectBase<INT64_PIECES, 2 * INT64_PIECES + 1> {
2787  public:
2788   LIR_HEADER(WasmSelectI64);
2789 
2790   static const size_t TrueExprIndex = 0;
2791   static const size_t FalseExprIndex = INT64_PIECES;
2792   static const size_t CondIndex = INT64_PIECES * 2;
2793 
LWasmSelectI64(const LInt64Allocation & trueExpr,const LInt64Allocation & falseExpr,const LAllocation & cond)2794   LWasmSelectI64(const LInt64Allocation& trueExpr,
2795                  const LInt64Allocation& falseExpr, const LAllocation& cond)
2796       : LWasmSelectBase(classOpcode) {
2797     setInt64Operand(TrueExprIndex, trueExpr);
2798     setInt64Operand(FalseExprIndex, falseExpr);
2799     setOperand(CondIndex, cond);
2800   }
2801 
trueExpr()2802   const LInt64Allocation trueExpr() { return getInt64Operand(TrueExprIndex); }
falseExpr()2803   const LInt64Allocation falseExpr() { return getInt64Operand(FalseExprIndex); }
condExpr()2804   const LAllocation* condExpr() { return getOperand(CondIndex); }
2805 };
2806 
2807 class LWasmCompareAndSelect : public LWasmSelectBase<1, 4> {
2808   MCompare::CompareType compareType_;
2809   JSOp jsop_;
2810 
2811  public:
2812   LIR_HEADER(WasmCompareAndSelect);
2813 
2814   static const size_t LeftExprIndex = 0;
2815   static const size_t RightExprIndex = 1;
2816   static const size_t IfTrueExprIndex = 2;
2817   static const size_t IfFalseExprIndex = 3;
2818 
LWasmCompareAndSelect(const LAllocation & leftExpr,const LAllocation & rightExpr,MCompare::CompareType compareType,JSOp jsop,const LAllocation & ifTrueExpr,const LAllocation & ifFalseExpr)2819   LWasmCompareAndSelect(const LAllocation& leftExpr,
2820                         const LAllocation& rightExpr,
2821                         MCompare::CompareType compareType, JSOp jsop,
2822                         const LAllocation& ifTrueExpr,
2823                         const LAllocation& ifFalseExpr)
2824       : LWasmSelectBase(classOpcode), compareType_(compareType), jsop_(jsop) {
2825     setOperand(LeftExprIndex, leftExpr);
2826     setOperand(RightExprIndex, rightExpr);
2827     setOperand(IfTrueExprIndex, ifTrueExpr);
2828     setOperand(IfFalseExprIndex, ifFalseExpr);
2829   }
2830 
leftExpr()2831   const LAllocation* leftExpr() { return getOperand(LeftExprIndex); }
rightExpr()2832   const LAllocation* rightExpr() { return getOperand(RightExprIndex); }
ifTrueExpr()2833   const LAllocation* ifTrueExpr() { return getOperand(IfTrueExprIndex); }
ifFalseExpr()2834   const LAllocation* ifFalseExpr() { return getOperand(IfFalseExprIndex); }
2835 
compareType()2836   MCompare::CompareType compareType() { return compareType_; }
jsop()2837   JSOp jsop() { return jsop_; }
2838 };
2839 
2840 class LWasmBoundsCheck64
2841     : public LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 0> {
2842  public:
2843   LIR_HEADER(WasmBoundsCheck64);
LWasmBoundsCheck64(const LInt64Allocation & ptr,const LInt64Allocation & boundsCheckLimit)2844   explicit LWasmBoundsCheck64(const LInt64Allocation& ptr,
2845                               const LInt64Allocation& boundsCheckLimit)
2846       : LInstructionHelper(classOpcode) {
2847     setInt64Operand(0, ptr);
2848     setInt64Operand(INT64_PIECES, boundsCheckLimit);
2849   }
mir()2850   MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); }
ptr()2851   LInt64Allocation ptr() { return getInt64Operand(0); }
boundsCheckLimit()2852   LInt64Allocation boundsCheckLimit() { return getInt64Operand(INT64_PIECES); }
2853 };
2854 
2855 namespace details {
2856 
2857 // This is a base class for LWasmLoad/LWasmLoadI64.
2858 template <size_t Defs, size_t Temp>
2859 class LWasmLoadBase : public LInstructionHelper<Defs, 2, Temp> {
2860  public:
2861   typedef LInstructionHelper<Defs, 2, Temp> Base;
LWasmLoadBase(LNode::Opcode opcode,const LAllocation & ptr,const LAllocation & memoryBase)2862   explicit LWasmLoadBase(LNode::Opcode opcode, const LAllocation& ptr,
2863                          const LAllocation& memoryBase)
2864       : Base(opcode) {
2865     Base::setOperand(0, ptr);
2866     Base::setOperand(1, memoryBase);
2867   }
mir()2868   MWasmLoad* mir() const { return Base::mir_->toWasmLoad(); }
ptr()2869   const LAllocation* ptr() { return Base::getOperand(0); }
memoryBase()2870   const LAllocation* memoryBase() { return Base::getOperand(1); }
2871 };
2872 
2873 }  // namespace details
2874 
2875 class LWasmLoad : public details::LWasmLoadBase<1, 1> {
2876  public:
2877   explicit LWasmLoad(const LAllocation& ptr,
2878                      const LAllocation& memoryBase = LAllocation())
LWasmLoadBase(classOpcode,ptr,memoryBase)2879       : LWasmLoadBase(classOpcode, ptr, memoryBase) {
2880     setTemp(0, LDefinition::BogusTemp());
2881   }
2882 
ptrCopy()2883   const LDefinition* ptrCopy() { return Base::getTemp(0); }
2884 
2885   LIR_HEADER(WasmLoad);
2886 };
2887 
2888 class LWasmLoadI64 : public details::LWasmLoadBase<INT64_PIECES, 1> {
2889  public:
2890   explicit LWasmLoadI64(const LAllocation& ptr,
2891                         const LAllocation& memoryBase = LAllocation())
LWasmLoadBase(classOpcode,ptr,memoryBase)2892       : LWasmLoadBase(classOpcode, ptr, memoryBase) {
2893     setTemp(0, LDefinition::BogusTemp());
2894   }
2895 
ptrCopy()2896   const LDefinition* ptrCopy() { return Base::getTemp(0); }
2897 
2898   LIR_HEADER(WasmLoadI64);
2899 };
2900 
2901 class LWasmStore : public LInstructionHelper<0, 3, 1> {
2902  public:
2903   LIR_HEADER(WasmStore);
2904 
2905   static const size_t PtrIndex = 0;
2906   static const size_t ValueIndex = 1;
2907   static const size_t MemoryBaseIndex = 2;
2908 
2909   LWasmStore(const LAllocation& ptr, const LAllocation& value,
2910              const LAllocation& memoryBase = LAllocation())
LInstructionHelper(classOpcode)2911       : LInstructionHelper(classOpcode) {
2912     setOperand(PtrIndex, ptr);
2913     setOperand(ValueIndex, value);
2914     setOperand(MemoryBaseIndex, memoryBase);
2915     setTemp(0, LDefinition::BogusTemp());
2916   }
mir()2917   MWasmStore* mir() const { return mir_->toWasmStore(); }
ptr()2918   const LAllocation* ptr() { return getOperand(PtrIndex); }
ptrCopy()2919   const LDefinition* ptrCopy() { return getTemp(0); }
value()2920   const LAllocation* value() { return getOperand(ValueIndex); }
memoryBase()2921   const LAllocation* memoryBase() { return getOperand(MemoryBaseIndex); }
2922 };
2923 
2924 class LWasmStoreI64 : public LInstructionHelper<0, INT64_PIECES + 2, 1> {
2925  public:
2926   LIR_HEADER(WasmStoreI64);
2927 
2928   static const size_t PtrIndex = 0;
2929   static const size_t MemoryBaseIndex = 1;
2930   static const size_t ValueIndex = 2;
2931 
2932   LWasmStoreI64(const LAllocation& ptr, const LInt64Allocation& value,
2933                 const LAllocation& memoryBase = LAllocation())
LInstructionHelper(classOpcode)2934       : LInstructionHelper(classOpcode) {
2935     setOperand(PtrIndex, ptr);
2936     setOperand(MemoryBaseIndex, memoryBase);
2937     setInt64Operand(ValueIndex, value);
2938     setTemp(0, LDefinition::BogusTemp());
2939   }
mir()2940   MWasmStore* mir() const { return mir_->toWasmStore(); }
ptr()2941   const LAllocation* ptr() { return getOperand(PtrIndex); }
memoryBase()2942   const LAllocation* memoryBase() { return getOperand(MemoryBaseIndex); }
ptrCopy()2943   const LDefinition* ptrCopy() { return getTemp(0); }
value()2944   const LInt64Allocation value() { return getInt64Operand(ValueIndex); }
2945 };
2946 
2947 class LWasmCompareExchangeHeap : public LInstructionHelper<1, 4, 4> {
2948  public:
2949   LIR_HEADER(WasmCompareExchangeHeap);
2950 
2951   // ARM, ARM64, x86, x64
2952   LWasmCompareExchangeHeap(const LAllocation& ptr, const LAllocation& oldValue,
2953                            const LAllocation& newValue,
2954                            const LAllocation& memoryBase = LAllocation())
LInstructionHelper(classOpcode)2955       : LInstructionHelper(classOpcode) {
2956     setOperand(0, ptr);
2957     setOperand(1, oldValue);
2958     setOperand(2, newValue);
2959     setOperand(3, memoryBase);
2960     setTemp(0, LDefinition::BogusTemp());
2961   }
2962   // MIPS32, MIPS64
LWasmCompareExchangeHeap(const LAllocation & ptr,const LAllocation & oldValue,const LAllocation & newValue,const LDefinition & valueTemp,const LDefinition & offsetTemp,const LDefinition & maskTemp)2963   LWasmCompareExchangeHeap(const LAllocation& ptr, const LAllocation& oldValue,
2964                            const LAllocation& newValue,
2965                            const LDefinition& valueTemp,
2966                            const LDefinition& offsetTemp,
2967                            const LDefinition& maskTemp)
2968       : LInstructionHelper(classOpcode) {
2969     setOperand(0, ptr);
2970     setOperand(1, oldValue);
2971     setOperand(2, newValue);
2972     setOperand(3, LAllocation());
2973     setTemp(0, LDefinition::BogusTemp());
2974     setTemp(1, valueTemp);
2975     setTemp(2, offsetTemp);
2976     setTemp(3, maskTemp);
2977   }
2978 
ptr()2979   const LAllocation* ptr() { return getOperand(0); }
oldValue()2980   const LAllocation* oldValue() { return getOperand(1); }
newValue()2981   const LAllocation* newValue() { return getOperand(2); }
memoryBase()2982   const LAllocation* memoryBase() { return getOperand(3); }
addrTemp()2983   const LDefinition* addrTemp() { return getTemp(0); }
2984 
setAddrTemp(const LDefinition & addrTemp)2985   void setAddrTemp(const LDefinition& addrTemp) { setTemp(0, addrTemp); }
2986 
2987   // Temp that may be used on LL/SC platforms for extract/insert bits of word.
valueTemp()2988   const LDefinition* valueTemp() { return getTemp(1); }
offsetTemp()2989   const LDefinition* offsetTemp() { return getTemp(2); }
maskTemp()2990   const LDefinition* maskTemp() { return getTemp(3); }
2991 
mir()2992   MWasmCompareExchangeHeap* mir() const {
2993     return mir_->toWasmCompareExchangeHeap();
2994   }
2995 };
2996 
2997 class LWasmAtomicExchangeHeap : public LInstructionHelper<1, 3, 4> {
2998  public:
2999   LIR_HEADER(WasmAtomicExchangeHeap);
3000 
3001   // ARM, ARM64, x86, x64
3002   LWasmAtomicExchangeHeap(const LAllocation& ptr, const LAllocation& value,
3003                           const LAllocation& memoryBase = LAllocation())
LInstructionHelper(classOpcode)3004       : LInstructionHelper(classOpcode) {
3005     setOperand(0, ptr);
3006     setOperand(1, value);
3007     setOperand(2, memoryBase);
3008     setTemp(0, LDefinition::BogusTemp());
3009   }
3010   // MIPS32, MIPS64
LWasmAtomicExchangeHeap(const LAllocation & ptr,const LAllocation & value,const LDefinition & valueTemp,const LDefinition & offsetTemp,const LDefinition & maskTemp)3011   LWasmAtomicExchangeHeap(const LAllocation& ptr, const LAllocation& value,
3012                           const LDefinition& valueTemp,
3013                           const LDefinition& offsetTemp,
3014                           const LDefinition& maskTemp)
3015       : LInstructionHelper(classOpcode) {
3016     setOperand(0, ptr);
3017     setOperand(1, value);
3018     setOperand(2, LAllocation());
3019     setTemp(0, LDefinition::BogusTemp());
3020     setTemp(1, valueTemp);
3021     setTemp(2, offsetTemp);
3022     setTemp(3, maskTemp);
3023   }
3024 
ptr()3025   const LAllocation* ptr() { return getOperand(0); }
value()3026   const LAllocation* value() { return getOperand(1); }
memoryBase()3027   const LAllocation* memoryBase() { return getOperand(2); }
addrTemp()3028   const LDefinition* addrTemp() { return getTemp(0); }
3029 
setAddrTemp(const LDefinition & addrTemp)3030   void setAddrTemp(const LDefinition& addrTemp) { setTemp(0, addrTemp); }
3031 
3032   // Temp that may be used on LL/SC platforms for extract/insert bits of word.
valueTemp()3033   const LDefinition* valueTemp() { return getTemp(1); }
offsetTemp()3034   const LDefinition* offsetTemp() { return getTemp(2); }
maskTemp()3035   const LDefinition* maskTemp() { return getTemp(3); }
3036 
mir()3037   MWasmAtomicExchangeHeap* mir() const {
3038     return mir_->toWasmAtomicExchangeHeap();
3039   }
3040 };
3041 
3042 class LWasmAtomicBinopHeap : public LInstructionHelper<1, 3, 6> {
3043  public:
3044   LIR_HEADER(WasmAtomicBinopHeap);
3045 
3046   static const int32_t valueOp = 1;
3047 
3048   // ARM, ARM64, x86, x64
3049   LWasmAtomicBinopHeap(const LAllocation& ptr, const LAllocation& value,
3050                        const LDefinition& temp,
3051                        const LDefinition& flagTemp = LDefinition::BogusTemp(),
3052                        const LAllocation& memoryBase = LAllocation())
LInstructionHelper(classOpcode)3053       : LInstructionHelper(classOpcode) {
3054     setOperand(0, ptr);
3055     setOperand(1, value);
3056     setOperand(2, memoryBase);
3057     setTemp(0, temp);
3058     setTemp(1, LDefinition::BogusTemp());
3059     setTemp(2, flagTemp);
3060   }
3061   // MIPS32, MIPS64
LWasmAtomicBinopHeap(const LAllocation & ptr,const LAllocation & value,const LDefinition & valueTemp,const LDefinition & offsetTemp,const LDefinition & maskTemp)3062   LWasmAtomicBinopHeap(const LAllocation& ptr, const LAllocation& value,
3063                        const LDefinition& valueTemp,
3064                        const LDefinition& offsetTemp,
3065                        const LDefinition& maskTemp)
3066       : LInstructionHelper(classOpcode) {
3067     setOperand(0, ptr);
3068     setOperand(1, value);
3069     setOperand(2, LAllocation());
3070     setTemp(0, LDefinition::BogusTemp());
3071     setTemp(1, LDefinition::BogusTemp());
3072     setTemp(2, LDefinition::BogusTemp());
3073     setTemp(3, valueTemp);
3074     setTemp(4, offsetTemp);
3075     setTemp(5, maskTemp);
3076   }
ptr()3077   const LAllocation* ptr() { return getOperand(0); }
value()3078   const LAllocation* value() {
3079     MOZ_ASSERT(valueOp == 1);
3080     return getOperand(1);
3081   }
memoryBase()3082   const LAllocation* memoryBase() { return getOperand(2); }
temp()3083   const LDefinition* temp() { return getTemp(0); }
3084 
3085   // Temp that may be used on some platforms to hold a computed address.
addrTemp()3086   const LDefinition* addrTemp() { return getTemp(1); }
setAddrTemp(const LDefinition & addrTemp)3087   void setAddrTemp(const LDefinition& addrTemp) { setTemp(1, addrTemp); }
3088 
3089   // Temp that may be used on LL/SC platforms for the flag result of the store.
flagTemp()3090   const LDefinition* flagTemp() { return getTemp(2); }
3091   // Temp that may be used on LL/SC platforms for extract/insert bits of word.
valueTemp()3092   const LDefinition* valueTemp() { return getTemp(3); }
offsetTemp()3093   const LDefinition* offsetTemp() { return getTemp(4); }
maskTemp()3094   const LDefinition* maskTemp() { return getTemp(5); }
3095 
mir()3096   MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); }
3097 };
3098 
3099 // Atomic binary operation where the result is discarded.
3100 class LWasmAtomicBinopHeapForEffect : public LInstructionHelper<0, 3, 5> {
3101  public:
3102   LIR_HEADER(WasmAtomicBinopHeapForEffect);
3103   // ARM, ARM64, x86, x64
3104   LWasmAtomicBinopHeapForEffect(
3105       const LAllocation& ptr, const LAllocation& value,
3106       const LDefinition& flagTemp = LDefinition::BogusTemp(),
3107       const LAllocation& memoryBase = LAllocation())
LInstructionHelper(classOpcode)3108       : LInstructionHelper(classOpcode) {
3109     setOperand(0, ptr);
3110     setOperand(1, value);
3111     setOperand(2, memoryBase);
3112     setTemp(0, LDefinition::BogusTemp());
3113     setTemp(1, flagTemp);
3114   }
3115   // MIPS32, MIPS64
LWasmAtomicBinopHeapForEffect(const LAllocation & ptr,const LAllocation & value,const LDefinition & valueTemp,const LDefinition & offsetTemp,const LDefinition & maskTemp)3116   LWasmAtomicBinopHeapForEffect(const LAllocation& ptr,
3117                                 const LAllocation& value,
3118                                 const LDefinition& valueTemp,
3119                                 const LDefinition& offsetTemp,
3120                                 const LDefinition& maskTemp)
3121       : LInstructionHelper(classOpcode) {
3122     setOperand(0, ptr);
3123     setOperand(1, value);
3124     setOperand(2, LAllocation());
3125     setTemp(0, LDefinition::BogusTemp());
3126     setTemp(1, LDefinition::BogusTemp());
3127     setTemp(2, valueTemp);
3128     setTemp(3, offsetTemp);
3129     setTemp(4, maskTemp);
3130   }
ptr()3131   const LAllocation* ptr() { return getOperand(0); }
value()3132   const LAllocation* value() { return getOperand(1); }
memoryBase()3133   const LAllocation* memoryBase() { return getOperand(2); }
3134 
3135   // Temp that may be used on some platforms to hold a computed address.
addrTemp()3136   const LDefinition* addrTemp() { return getTemp(0); }
setAddrTemp(const LDefinition & addrTemp)3137   void setAddrTemp(const LDefinition& addrTemp) { setTemp(0, addrTemp); }
3138 
3139   // Temp that may be used on LL/SC platforms for the flag result of the store.
flagTemp()3140   const LDefinition* flagTemp() { return getTemp(1); }
3141   // Temp that may be used on LL/SC platforms for extract/insert bits of word.
valueTemp()3142   const LDefinition* valueTemp() { return getTemp(2); }
offsetTemp()3143   const LDefinition* offsetTemp() { return getTemp(3); }
maskTemp()3144   const LDefinition* maskTemp() { return getTemp(4); }
3145 
mir()3146   MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); }
3147 };
3148 
3149 class LWasmDerivedPointer : public LInstructionHelper<1, 1, 0> {
3150  public:
3151   LIR_HEADER(WasmDerivedPointer);
LWasmDerivedPointer(const LAllocation & base)3152   explicit LWasmDerivedPointer(const LAllocation& base)
3153       : LInstructionHelper(classOpcode) {
3154     setOperand(0, base);
3155   }
base()3156   const LAllocation* base() { return getOperand(0); }
offset()3157   size_t offset() { return mirRaw()->toWasmDerivedPointer()->offset(); }
3158 };
3159 
3160 class LWasmParameterI64 : public LInstructionHelper<INT64_PIECES, 0, 0> {
3161  public:
3162   LIR_HEADER(WasmParameterI64);
3163 
LWasmParameterI64()3164   LWasmParameterI64() : LInstructionHelper(classOpcode) {}
3165 };
3166 
3167 // This is used only with LWasmCall.
3168 class LWasmCallIndirectAdjunctSafepoint : public LInstructionHelper<0, 0, 0> {
3169   CodeOffset offs_;
3170   uint32_t framePushedAtStackMapBase_;
3171 
3172  public:
3173   LIR_HEADER(WasmCallIndirectAdjunctSafepoint);
3174 
LWasmCallIndirectAdjunctSafepoint()3175   LWasmCallIndirectAdjunctSafepoint()
3176       : LInstructionHelper(classOpcode),
3177         offs_(0),
3178         framePushedAtStackMapBase_(0) {}
3179 
safepointLocation()3180   CodeOffset safepointLocation() const {
3181     MOZ_ASSERT(offs_.offset() != 0);
3182     return offs_;
3183   }
framePushedAtStackMapBase()3184   uint32_t framePushedAtStackMapBase() const {
3185     MOZ_ASSERT(offs_.offset() != 0);
3186     return framePushedAtStackMapBase_;
3187   }
recordSafepointInfo(CodeOffset offs,uint32_t framePushed)3188   void recordSafepointInfo(CodeOffset offs, uint32_t framePushed) {
3189     offs_ = offs;
3190     framePushedAtStackMapBase_ = framePushed;
3191   }
3192 };
3193 
3194 // LWasmCall may be generated into two function calls in the case of
3195 // call_indirect, one for the fast path and one for the slow path.  In that
3196 // case, the node carries a pointer to a companion node, the "adjunct
3197 // safepoint", representing the safepoint for the second of the two calls.  The
3198 // dual-call construction is only meaningful for wasm because wasm has no
3199 // invalidation of code; this is not a pattern to be used generally.
3200 class LWasmCall : public LVariadicInstruction<0, 0> {
3201   bool needsBoundsCheck_;
3202   mozilla::Maybe<uint32_t> tableSize_;
3203   LWasmCallIndirectAdjunctSafepoint* adjunctSafepoint_;
3204 
3205  public:
3206   LIR_HEADER(WasmCall);
3207 
3208   LWasmCall(uint32_t numOperands, bool needsBoundsCheck,
3209             mozilla::Maybe<uint32_t> tableSize = mozilla::Nothing())
LVariadicInstruction(classOpcode,numOperands)3210       : LVariadicInstruction(classOpcode, numOperands),
3211         needsBoundsCheck_(needsBoundsCheck),
3212         tableSize_(tableSize),
3213         adjunctSafepoint_(nullptr) {
3214     this->setIsCall();
3215   }
3216 
mir()3217   MWasmCall* mir() const { return mir_->toWasmCall(); }
3218 
isCallPreserved(AnyRegister reg)3219   static bool isCallPreserved(AnyRegister reg) {
3220     // All MWasmCalls preserve the TLS register:
3221     //  - internal/indirect calls do by the internal wasm ABI
3222     //  - import calls do by explicitly saving/restoring at the callsite
3223     //  - builtin calls do because the TLS reg is non-volatile
3224     // See also CodeGeneratorShared::emitWasmCall.
3225     return !reg.isFloat() && reg.gpr() == WasmTlsReg;
3226   }
3227 
needsBoundsCheck()3228   bool needsBoundsCheck() const { return needsBoundsCheck_; }
tableSize()3229   mozilla::Maybe<uint32_t> tableSize() const { return tableSize_; }
adjunctSafepoint()3230   LWasmCallIndirectAdjunctSafepoint* adjunctSafepoint() const {
3231     MOZ_ASSERT(adjunctSafepoint_ != nullptr);
3232     return adjunctSafepoint_;
3233   }
setAdjunctSafepoint(LWasmCallIndirectAdjunctSafepoint * asp)3234   void setAdjunctSafepoint(LWasmCallIndirectAdjunctSafepoint* asp) {
3235     adjunctSafepoint_ = asp;
3236   }
3237 };
3238 
3239 class LWasmRegisterResult : public LInstructionHelper<1, 0, 0> {
3240  public:
3241   LIR_HEADER(WasmRegisterResult);
3242 
LWasmRegisterResult()3243   LWasmRegisterResult() : LInstructionHelper(classOpcode) {}
3244 
mir()3245   MWasmRegisterResult* mir() const {
3246     if (!mir_->isWasmRegisterResult()) {
3247       return nullptr;
3248     }
3249     return mir_->toWasmRegisterResult();
3250   }
3251 };
3252 
3253 class LWasmRegisterPairResult : public LInstructionHelper<2, 0, 0> {
3254  public:
3255   LIR_HEADER(WasmRegisterPairResult);
3256 
LWasmRegisterPairResult()3257   LWasmRegisterPairResult() : LInstructionHelper(classOpcode) {}
3258 
mir()3259   MDefinition* mir() const { return mirRaw(); }
3260 };
3261 
base()3262 inline uint32_t LStackArea::base() const {
3263   return ins()->toWasmStackResultArea()->mir()->base();
3264 }
setBase(uint32_t base)3265 inline void LStackArea::setBase(uint32_t base) {
3266   ins()->toWasmStackResultArea()->mir()->setBase(base);
3267 }
size()3268 inline uint32_t LStackArea::size() const {
3269   return ins()->toWasmStackResultArea()->mir()->byteSize();
3270 }
3271 
done()3272 inline bool LStackArea::ResultIterator::done() const {
3273   return idx_ == alloc_.ins()->toWasmStackResultArea()->mir()->resultCount();
3274 }
next()3275 inline void LStackArea::ResultIterator::next() {
3276   MOZ_ASSERT(!done());
3277   idx_++;
3278 }
alloc()3279 inline LAllocation LStackArea::ResultIterator::alloc() const {
3280   MOZ_ASSERT(!done());
3281   MWasmStackResultArea* area = alloc_.ins()->toWasmStackResultArea()->mir();
3282   return LStackSlot(area->base() - area->result(idx_).offset());
3283 }
isGcPointer()3284 inline bool LStackArea::ResultIterator::isGcPointer() const {
3285   MOZ_ASSERT(!done());
3286   MWasmStackResultArea* area = alloc_.ins()->toWasmStackResultArea()->mir();
3287   MIRType type = area->result(idx_).type();
3288 #ifndef JS_PUNBOX64
3289   // LDefinition::TypeFrom isn't defined for MIRType::Int64 values on
3290   // this platform, so here we have a special case.
3291   if (type == MIRType::Int64) {
3292     return false;
3293   }
3294 #endif
3295   return LDefinition::TypeFrom(type) == LDefinition::OBJECT;
3296 }
3297 
3298 class LWasmStackResult : public LInstructionHelper<1, 1, 0> {
3299  public:
3300   LIR_HEADER(WasmStackResult);
3301 
LWasmStackResult()3302   LWasmStackResult() : LInstructionHelper(classOpcode) {}
3303 
mir()3304   MWasmStackResult* mir() const { return mir_->toWasmStackResult(); }
result(uint32_t base)3305   LStackSlot result(uint32_t base) const {
3306     return LStackSlot(base - mir()->result().offset());
3307   }
3308 };
3309 
3310 class LWasmStackResult64 : public LInstructionHelper<INT64_PIECES, 1, 0> {
3311  public:
3312   LIR_HEADER(WasmStackResult64);
3313 
LWasmStackResult64()3314   LWasmStackResult64() : LInstructionHelper(classOpcode) {}
3315 
mir()3316   MWasmStackResult* mir() const { return mir_->toWasmStackResult(); }
result(uint32_t base,LDefinition * def)3317   LStackSlot result(uint32_t base, LDefinition* def) {
3318     uint32_t offset = base - mir()->result().offset();
3319 #if defined(JS_NUNBOX32)
3320     if (def == getDef(INT64LOW_INDEX)) {
3321       offset -= INT64LOW_OFFSET;
3322     } else {
3323       MOZ_ASSERT(def == getDef(INT64HIGH_INDEX));
3324       offset -= INT64HIGH_OFFSET;
3325     }
3326 #else
3327     MOZ_ASSERT(def == getDef(0));
3328 #endif
3329     return LStackSlot(offset);
3330   }
3331 };
3332 
resultAlloc(LInstruction * lir,LDefinition * def)3333 inline LStackSlot LStackArea::resultAlloc(LInstruction* lir,
3334                                           LDefinition* def) const {
3335   if (lir->isWasmStackResult64()) {
3336     return lir->toWasmStackResult64()->result(base(), def);
3337   }
3338   MOZ_ASSERT(def == lir->getDef(0));
3339   return lir->toWasmStackResult()->result(base());
3340 }
3341 
isCallPreserved(AnyRegister reg)3342 inline bool LNode::isCallPreserved(AnyRegister reg) const {
3343   return isWasmCall() && LWasmCall::isCallPreserved(reg);
3344 }
3345 
3346 class LAssertRangeI : public LInstructionHelper<0, 1, 0> {
3347  public:
LIR_HEADER(AssertRangeI)3348   LIR_HEADER(AssertRangeI)
3349 
3350   explicit LAssertRangeI(const LAllocation& input)
3351       : LInstructionHelper(classOpcode) {
3352     setOperand(0, input);
3353   }
3354 
input()3355   const LAllocation* input() { return getOperand(0); }
3356 
mir()3357   MAssertRange* mir() { return mir_->toAssertRange(); }
range()3358   const Range* range() { return mir()->assertedRange(); }
3359 };
3360 
3361 class LAssertRangeD : public LInstructionHelper<0, 1, 1> {
3362  public:
LIR_HEADER(AssertRangeD)3363   LIR_HEADER(AssertRangeD)
3364 
3365   LAssertRangeD(const LAllocation& input, const LDefinition& temp)
3366       : LInstructionHelper(classOpcode) {
3367     setOperand(0, input);
3368     setTemp(0, temp);
3369   }
3370 
input()3371   const LAllocation* input() { return getOperand(0); }
3372 
temp()3373   const LDefinition* temp() { return getTemp(0); }
3374 
mir()3375   MAssertRange* mir() { return mir_->toAssertRange(); }
range()3376   const Range* range() { return mir()->assertedRange(); }
3377 };
3378 
3379 class LAssertRangeF : public LInstructionHelper<0, 1, 2> {
3380  public:
LIR_HEADER(AssertRangeF)3381   LIR_HEADER(AssertRangeF)
3382   LAssertRangeF(const LAllocation& input, const LDefinition& temp,
3383                 const LDefinition& temp2)
3384       : LInstructionHelper(classOpcode) {
3385     setOperand(0, input);
3386     setTemp(0, temp);
3387     setTemp(1, temp2);
3388   }
3389 
input()3390   const LAllocation* input() { return getOperand(0); }
temp()3391   const LDefinition* temp() { return getTemp(0); }
temp2()3392   const LDefinition* temp2() { return getTemp(1); }
3393 
mir()3394   MAssertRange* mir() { return mir_->toAssertRange(); }
range()3395   const Range* range() { return mir()->assertedRange(); }
3396 };
3397 
3398 class LAssertRangeV : public LInstructionHelper<0, BOX_PIECES, 3> {
3399  public:
LIR_HEADER(AssertRangeV)3400   LIR_HEADER(AssertRangeV)
3401 
3402   LAssertRangeV(const LBoxAllocation& input, const LDefinition& temp,
3403                 const LDefinition& floatTemp1, const LDefinition& floatTemp2)
3404       : LInstructionHelper(classOpcode) {
3405     setBoxOperand(Input, input);
3406     setTemp(0, temp);
3407     setTemp(1, floatTemp1);
3408     setTemp(2, floatTemp2);
3409   }
3410 
3411   static const size_t Input = 0;
3412 
temp()3413   const LDefinition* temp() { return getTemp(0); }
floatTemp1()3414   const LDefinition* floatTemp1() { return getTemp(1); }
floatTemp2()3415   const LDefinition* floatTemp2() { return getTemp(2); }
3416 
mir()3417   MAssertRange* mir() { return mir_->toAssertRange(); }
range()3418   const Range* range() { return mir()->assertedRange(); }
3419 };
3420 
3421 class LMemoryBarrier : public LInstructionHelper<0, 0, 0> {
3422  private:
3423   const MemoryBarrierBits type_;
3424 
3425  public:
LIR_HEADER(MemoryBarrier)3426   LIR_HEADER(MemoryBarrier)
3427 
3428   // The parameter 'type' is a bitwise 'or' of the barrier types needed,
3429   // see AtomicOp.h.
3430   explicit LMemoryBarrier(MemoryBarrierBits type)
3431       : LInstructionHelper(classOpcode), type_(type) {
3432     MOZ_ASSERT((type_ & ~MembarAllbits) == MembarNobits);
3433   }
3434 
type()3435   MemoryBarrierBits type() const { return type_; }
3436 };
3437 
3438 // Math.random().
3439 class LRandom : public LInstructionHelper<1, 0, 1 + 2 * INT64_PIECES> {
3440  public:
LIR_HEADER(Random)3441   LIR_HEADER(Random)
3442   LRandom(const LDefinition& temp0, const LInt64Definition& temp1,
3443           const LInt64Definition& temp2)
3444       : LInstructionHelper(classOpcode) {
3445     setTemp(0, temp0);
3446     setInt64Temp(1, temp1);
3447     setInt64Temp(1 + INT64_PIECES, temp2);
3448   }
temp0()3449   const LDefinition* temp0() { return getTemp(0); }
temp1()3450   LInt64Definition temp1() { return getInt64Temp(1); }
temp2()3451   LInt64Definition temp2() { return getInt64Temp(1 + INT64_PIECES); }
3452 
mir()3453   MRandom* mir() const { return mir_->toRandom(); }
3454 };
3455 
3456 class LBigIntAsIntN64 : public LInstructionHelper<1, 1, 1 + INT64_PIECES> {
3457  public:
LIR_HEADER(BigIntAsIntN64)3458   LIR_HEADER(BigIntAsIntN64)
3459 
3460   LBigIntAsIntN64(const LAllocation& input, const LDefinition& temp,
3461                   const LInt64Definition& temp64)
3462       : LInstructionHelper(classOpcode) {
3463     setOperand(0, input);
3464     setTemp(0, temp);
3465     setInt64Temp(1, temp64);
3466   }
3467 
input()3468   const LAllocation* input() { return getOperand(0); }
temp()3469   const LDefinition* temp() { return getTemp(0); }
temp64()3470   LInt64Definition temp64() { return getInt64Temp(1); }
3471 };
3472 
3473 class LBigIntAsIntN32 : public LInstructionHelper<1, 1, 1 + INT64_PIECES> {
3474  public:
LIR_HEADER(BigIntAsIntN32)3475   LIR_HEADER(BigIntAsIntN32)
3476 
3477   LBigIntAsIntN32(const LAllocation& input, const LDefinition& temp,
3478                   const LInt64Definition& temp64)
3479       : LInstructionHelper(classOpcode) {
3480     setOperand(0, input);
3481     setTemp(0, temp);
3482     setInt64Temp(1, temp64);
3483   }
3484 
input()3485   const LAllocation* input() { return getOperand(0); }
temp()3486   const LDefinition* temp() { return getTemp(0); }
temp64()3487   LInt64Definition temp64() { return getInt64Temp(1); }
3488 };
3489 
3490 class LBigIntAsUintN64 : public LInstructionHelper<1, 1, 1 + INT64_PIECES> {
3491  public:
LIR_HEADER(BigIntAsUintN64)3492   LIR_HEADER(BigIntAsUintN64)
3493 
3494   LBigIntAsUintN64(const LAllocation& input, const LDefinition& temp,
3495                    const LInt64Definition& temp64)
3496       : LInstructionHelper(classOpcode) {
3497     setOperand(0, input);
3498     setTemp(0, temp);
3499     setInt64Temp(1, temp64);
3500   }
3501 
input()3502   const LAllocation* input() { return getOperand(0); }
temp()3503   const LDefinition* temp() { return getTemp(0); }
temp64()3504   LInt64Definition temp64() { return getInt64Temp(1); }
3505 };
3506 
3507 class LBigIntAsUintN32 : public LInstructionHelper<1, 1, 1 + INT64_PIECES> {
3508  public:
LIR_HEADER(BigIntAsUintN32)3509   LIR_HEADER(BigIntAsUintN32)
3510 
3511   LBigIntAsUintN32(const LAllocation& input, const LDefinition& temp,
3512                    const LInt64Definition& temp64)
3513       : LInstructionHelper(classOpcode) {
3514     setOperand(0, input);
3515     setTemp(0, temp);
3516     setInt64Temp(1, temp64);
3517   }
3518 
input()3519   const LAllocation* input() { return getOperand(0); }
temp()3520   const LDefinition* temp() { return getTemp(0); }
temp64()3521   LInt64Definition temp64() { return getInt64Temp(1); }
3522 };
3523 
3524 template <size_t NumDefs>
3525 class LIonToWasmCallBase : public LVariadicInstruction<NumDefs, 2> {
3526   using Base = LVariadicInstruction<NumDefs, 2>;
3527 
3528  public:
LIonToWasmCallBase(LNode::Opcode classOpcode,uint32_t numOperands,const LDefinition & temp,const LDefinition & fp)3529   explicit LIonToWasmCallBase(LNode::Opcode classOpcode, uint32_t numOperands,
3530                               const LDefinition& temp, const LDefinition& fp)
3531       : Base(classOpcode, numOperands) {
3532     this->setIsCall();
3533     this->setTemp(0, temp);
3534     this->setTemp(1, fp);
3535   }
mir()3536   MIonToWasmCall* mir() const { return this->mir_->toIonToWasmCall(); }
temp()3537   const LDefinition* temp() { return this->getTemp(0); }
3538 };
3539 
3540 class LIonToWasmCall : public LIonToWasmCallBase<1> {
3541  public:
3542   LIR_HEADER(IonToWasmCall);
LIonToWasmCall(uint32_t numOperands,const LDefinition & temp,const LDefinition & fp)3543   LIonToWasmCall(uint32_t numOperands, const LDefinition& temp,
3544                  const LDefinition& fp)
3545       : LIonToWasmCallBase<1>(classOpcode, numOperands, temp, fp) {}
3546 };
3547 
3548 class LIonToWasmCallV : public LIonToWasmCallBase<BOX_PIECES> {
3549  public:
3550   LIR_HEADER(IonToWasmCallV);
LIonToWasmCallV(uint32_t numOperands,const LDefinition & temp,const LDefinition & fp)3551   LIonToWasmCallV(uint32_t numOperands, const LDefinition& temp,
3552                   const LDefinition& fp)
3553       : LIonToWasmCallBase<BOX_PIECES>(classOpcode, numOperands, temp, fp) {}
3554 };
3555 
3556 class LIonToWasmCallI64 : public LIonToWasmCallBase<INT64_PIECES> {
3557  public:
3558   LIR_HEADER(IonToWasmCallI64);
LIonToWasmCallI64(uint32_t numOperands,const LDefinition & temp,const LDefinition & fp)3559   LIonToWasmCallI64(uint32_t numOperands, const LDefinition& temp,
3560                     const LDefinition& fp)
3561       : LIonToWasmCallBase<INT64_PIECES>(classOpcode, numOperands, temp, fp) {}
3562 };
3563 // Wasm SIMD.
3564 
3565 // (v128, v128, v128) -> v128 effect-free operation.
3566 // temp is FPR.
3567 class LWasmTernarySimd128 : public LInstructionHelper<1, 3, 1> {
3568   wasm::SimdOp op_;
3569 
3570  public:
3571   LIR_HEADER(WasmTernarySimd128)
3572 
3573   static constexpr uint32_t V0 = 0;
3574   static constexpr uint32_t V1 = 1;
3575   static constexpr uint32_t V2 = 2;
3576 
LWasmTernarySimd128(wasm::SimdOp op,const LAllocation & v0,const LAllocation & v1,const LAllocation & v2)3577   LWasmTernarySimd128(wasm::SimdOp op, const LAllocation& v0,
3578                       const LAllocation& v1, const LAllocation& v2)
3579       : LInstructionHelper(classOpcode), op_(op) {
3580     setOperand(V0, v0);
3581     setOperand(V1, v1);
3582     setOperand(V2, v2);
3583   }
3584 
LWasmTernarySimd128(wasm::SimdOp op,const LAllocation & v0,const LAllocation & v1,const LAllocation & v2,const LDefinition & temp)3585   LWasmTernarySimd128(wasm::SimdOp op, const LAllocation& v0,
3586                       const LAllocation& v1, const LAllocation& v2,
3587                       const LDefinition& temp)
3588       : LInstructionHelper(classOpcode), op_(op) {
3589     setOperand(V0, v0);
3590     setOperand(V1, v1);
3591     setOperand(V2, v2);
3592     setTemp(0, temp);
3593   }
3594 
v0()3595   const LAllocation* v0() { return getOperand(V0); }
v1()3596   const LAllocation* v1() { return getOperand(V1); }
v2()3597   const LAllocation* v2() { return getOperand(V2); }
temp()3598   const LDefinition* temp() { return getTemp(0); }
3599 
simdOp()3600   wasm::SimdOp simdOp() const { return op_; }
3601 };
3602 
3603 // (v128, v128) -> v128 effect-free operations
3604 // lhs and dest are the same.
3605 // temps (if in use) are FPR.
3606 // The op may differ from the MIR node's op.
3607 class LWasmBinarySimd128 : public LInstructionHelper<1, 2, 2> {
3608   wasm::SimdOp op_;
3609 
3610  public:
3611   LIR_HEADER(WasmBinarySimd128)
3612 
3613   static constexpr uint32_t Lhs = 0;
3614   static constexpr uint32_t LhsDest = 0;
3615   static constexpr uint32_t Rhs = 1;
3616 
LWasmBinarySimd128(wasm::SimdOp op,const LAllocation & lhs,const LAllocation & rhs,const LDefinition & temp0,const LDefinition & temp1)3617   LWasmBinarySimd128(wasm::SimdOp op, const LAllocation& lhs,
3618                      const LAllocation& rhs, const LDefinition& temp0,
3619                      const LDefinition& temp1)
3620       : LInstructionHelper(classOpcode), op_(op) {
3621     setOperand(Lhs, lhs);
3622     setOperand(Rhs, rhs);
3623     setTemp(0, temp0);
3624     setTemp(1, temp1);
3625   }
3626 
lhs()3627   const LAllocation* lhs() { return getOperand(Lhs); }
lhsDest()3628   const LAllocation* lhsDest() { return getOperand(LhsDest); }
rhs()3629   const LAllocation* rhs() { return getOperand(Rhs); }
simdOp()3630   wasm::SimdOp simdOp() const { return op_; }
3631 
3632   static bool SpecializeForConstantRhs(wasm::SimdOp op);
3633 };
3634 
3635 class LWasmBinarySimd128WithConstant : public LInstructionHelper<1, 1, 0> {
3636   SimdConstant rhs_;
3637 
3638  public:
3639   LIR_HEADER(WasmBinarySimd128WithConstant)
3640 
3641   static constexpr uint32_t Lhs = 0;
3642   static constexpr uint32_t LhsDest = 0;
3643 
LWasmBinarySimd128WithConstant(const LAllocation & lhs,const SimdConstant & rhs)3644   LWasmBinarySimd128WithConstant(const LAllocation& lhs,
3645                                  const SimdConstant& rhs)
3646       : LInstructionHelper(classOpcode), rhs_(rhs) {
3647     setOperand(Lhs, lhs);
3648   }
3649 
lhs()3650   const LAllocation* lhs() { return getOperand(Lhs); }
lhsDest()3651   const LAllocation* lhsDest() { return getOperand(LhsDest); }
rhs()3652   const SimdConstant& rhs() { return rhs_; }
simdOp()3653   wasm::SimdOp simdOp() const {
3654     return mir_->toWasmBinarySimd128WithConstant()->simdOp();
3655   }
3656 };
3657 
3658 // (v128, i32) -> v128 effect-free variable-width shift operations
3659 // lhs and dest are the same.
3660 // temp is an FPR (if in use).
3661 class LWasmVariableShiftSimd128 : public LInstructionHelper<1, 2, 1> {
3662  public:
3663   LIR_HEADER(WasmVariableShiftSimd128)
3664 
3665   static constexpr uint32_t Lhs = 0;
3666   static constexpr uint32_t LhsDest = 0;
3667   static constexpr uint32_t Rhs = 1;
3668 
LWasmVariableShiftSimd128(const LAllocation & lhs,const LAllocation & rhs,const LDefinition & temp)3669   LWasmVariableShiftSimd128(const LAllocation& lhs, const LAllocation& rhs,
3670                             const LDefinition& temp)
3671       : LInstructionHelper(classOpcode) {
3672     setOperand(Lhs, lhs);
3673     setOperand(Rhs, rhs);
3674     setTemp(0, temp);
3675   }
3676 
lhs()3677   const LAllocation* lhs() { return getOperand(Lhs); }
lhsDest()3678   const LAllocation* lhsDest() { return getOperand(LhsDest); }
rhs()3679   const LAllocation* rhs() { return getOperand(Rhs); }
simdOp()3680   wasm::SimdOp simdOp() const { return mir_->toWasmShiftSimd128()->simdOp(); }
3681 };
3682 
3683 // (v128, i32) -> v128 effect-free constant-width shift operations
3684 class LWasmConstantShiftSimd128 : public LInstructionHelper<1, 1, 0> {
3685   int32_t shift_;
3686 
3687  public:
3688   LIR_HEADER(WasmConstantShiftSimd128)
3689 
3690   static constexpr uint32_t Src = 0;
3691 
LWasmConstantShiftSimd128(const LAllocation & src,int32_t shift)3692   LWasmConstantShiftSimd128(const LAllocation& src, int32_t shift)
3693       : LInstructionHelper(classOpcode), shift_(shift) {
3694     setOperand(Src, src);
3695   }
3696 
src()3697   const LAllocation* src() { return getOperand(Src); }
shift()3698   int32_t shift() { return shift_; }
simdOp()3699   wasm::SimdOp simdOp() const { return mir_->toWasmShiftSimd128()->simdOp(); }
3700 };
3701 
3702 // (v128) -> v128 sign replication operation.
3703 class LWasmSignReplicationSimd128 : public LInstructionHelper<1, 1, 0> {
3704  public:
3705   LIR_HEADER(WasmSignReplicationSimd128)
3706 
3707   static constexpr uint32_t Src = 0;
3708 
LWasmSignReplicationSimd128(const LAllocation & src)3709   explicit LWasmSignReplicationSimd128(const LAllocation& src)
3710       : LInstructionHelper(classOpcode) {
3711     setOperand(Src, src);
3712   }
3713 
src()3714   const LAllocation* src() { return getOperand(Src); }
simdOp()3715   wasm::SimdOp simdOp() const { return mir_->toWasmShiftSimd128()->simdOp(); }
3716 };
3717 
3718 // (v128, v128, imm_simd) -> v128 effect-free operation.
3719 // temp is FPR (and always in use).
3720 class LWasmShuffleSimd128 : public LInstructionHelper<1, 2, 1> {
3721  private:
3722   SimdShuffleOp op_;
3723   SimdConstant control_;
3724 
3725  public:
3726   LIR_HEADER(WasmShuffleSimd128)
3727 
3728   static constexpr uint32_t Lhs = 0;
3729   static constexpr uint32_t LhsDest = 0;
3730   static constexpr uint32_t Rhs = 1;
3731 
LWasmShuffleSimd128(const LAllocation & lhs,const LAllocation & rhs,const LDefinition & temp,SimdShuffleOp op,SimdConstant control)3732   LWasmShuffleSimd128(const LAllocation& lhs, const LAllocation& rhs,
3733                       const LDefinition& temp, SimdShuffleOp op,
3734                       SimdConstant control)
3735       : LInstructionHelper(classOpcode), op_(op), control_(control) {
3736     setOperand(Lhs, lhs);
3737     setOperand(Rhs, rhs);
3738     setTemp(0, temp);
3739   }
3740 
lhs()3741   const LAllocation* lhs() { return getOperand(Lhs); }
lhsDest()3742   const LAllocation* lhsDest() { return getOperand(LhsDest); }
rhs()3743   const LAllocation* rhs() { return getOperand(Rhs); }
temp()3744   const LDefinition* temp() { return getTemp(0); }
op()3745   SimdShuffleOp op() { return op_; }
control()3746   SimdConstant control() { return control_; }
3747 };
3748 
3749 // (v128, imm_simd) -> v128 effect-free operation.
3750 class LWasmPermuteSimd128 : public LInstructionHelper<1, 1, 0> {
3751  private:
3752   SimdPermuteOp op_;
3753   SimdConstant control_;
3754 
3755  public:
3756   LIR_HEADER(WasmPermuteSimd128)
3757 
3758   static constexpr uint32_t Src = 0;
3759 
LWasmPermuteSimd128(const LAllocation & src,SimdPermuteOp op,SimdConstant control)3760   LWasmPermuteSimd128(const LAllocation& src, SimdPermuteOp op,
3761                       SimdConstant control)
3762       : LInstructionHelper(classOpcode), op_(op), control_(control) {
3763     setOperand(Src, src);
3764   }
3765 
src()3766   const LAllocation* src() { return getOperand(Src); }
op()3767   SimdPermuteOp op() { return op_; }
control()3768   SimdConstant control() { return control_; }
3769 };
3770 
3771 class LWasmReplaceLaneSimd128 : public LInstructionHelper<1, 2, 0> {
3772  public:
3773   LIR_HEADER(WasmReplaceLaneSimd128)
3774 
3775   static constexpr uint32_t Lhs = 0;
3776   static constexpr uint32_t LhsDest = 0;
3777   static constexpr uint32_t Rhs = 1;
3778 
LWasmReplaceLaneSimd128(const LAllocation & lhs,const LAllocation & rhs)3779   LWasmReplaceLaneSimd128(const LAllocation& lhs, const LAllocation& rhs)
3780       : LInstructionHelper(classOpcode) {
3781     setOperand(Lhs, lhs);
3782     setOperand(Rhs, rhs);
3783   }
3784 
lhs()3785   const LAllocation* lhs() { return getOperand(Lhs); }
lhsDest()3786   const LAllocation* lhsDest() { return getOperand(LhsDest); }
rhs()3787   const LAllocation* rhs() { return getOperand(Rhs); }
laneIndex()3788   uint32_t laneIndex() const {
3789     return mir_->toWasmReplaceLaneSimd128()->laneIndex();
3790   }
simdOp()3791   wasm::SimdOp simdOp() const {
3792     return mir_->toWasmReplaceLaneSimd128()->simdOp();
3793   }
3794 };
3795 
3796 class LWasmReplaceInt64LaneSimd128
3797     : public LInstructionHelper<1, INT64_PIECES + 1, 0> {
3798  public:
3799   LIR_HEADER(WasmReplaceInt64LaneSimd128)
3800 
3801   static constexpr uint32_t Lhs = 0;
3802   static constexpr uint32_t LhsDest = 0;
3803   static constexpr uint32_t Rhs = 1;
3804 
LWasmReplaceInt64LaneSimd128(const LAllocation & lhs,const LInt64Allocation & rhs)3805   LWasmReplaceInt64LaneSimd128(const LAllocation& lhs,
3806                                const LInt64Allocation& rhs)
3807       : LInstructionHelper(classOpcode) {
3808     setOperand(Lhs, lhs);
3809     setInt64Operand(Rhs, rhs);
3810   }
3811 
lhs()3812   const LAllocation* lhs() { return getOperand(Lhs); }
lhsDest()3813   const LAllocation* lhsDest() { return getOperand(LhsDest); }
rhs()3814   const LInt64Allocation rhs() { return getInt64Operand(Rhs); }
output()3815   const LDefinition* output() { return this->getDef(0); }
laneIndex()3816   uint32_t laneIndex() const {
3817     return mir_->toWasmReplaceLaneSimd128()->laneIndex();
3818   }
simdOp()3819   wasm::SimdOp simdOp() const {
3820     return mir_->toWasmReplaceLaneSimd128()->simdOp();
3821   }
3822 };
3823 
3824 // (scalar) -> v128 effect-free operations, scalar != int64
3825 class LWasmScalarToSimd128 : public LInstructionHelper<1, 1, 0> {
3826  public:
3827   LIR_HEADER(WasmScalarToSimd128)
3828 
3829   static constexpr uint32_t Src = 0;
3830 
LWasmScalarToSimd128(const LAllocation & src)3831   explicit LWasmScalarToSimd128(const LAllocation& src)
3832       : LInstructionHelper(classOpcode) {
3833     setOperand(Src, src);
3834   }
3835 
src()3836   const LAllocation* src() { return getOperand(Src); }
simdOp()3837   wasm::SimdOp simdOp() const {
3838     return mir_->toWasmScalarToSimd128()->simdOp();
3839   }
3840 };
3841 
3842 // (int64) -> v128 effect-free operations
3843 class LWasmInt64ToSimd128 : public LInstructionHelper<1, INT64_PIECES, 0> {
3844  public:
3845   LIR_HEADER(WasmInt64ToSimd128)
3846 
3847   static constexpr uint32_t Src = 0;
3848 
LWasmInt64ToSimd128(const LInt64Allocation & src)3849   explicit LWasmInt64ToSimd128(const LInt64Allocation& src)
3850       : LInstructionHelper(classOpcode) {
3851     setInt64Operand(Src, src);
3852   }
3853 
src()3854   const LInt64Allocation src() { return getInt64Operand(Src); }
simdOp()3855   wasm::SimdOp simdOp() const {
3856     return mir_->toWasmScalarToSimd128()->simdOp();
3857   }
3858 };
3859 
3860 // (v128) -> v128 effect-free operations
3861 // temp is FPR (if in use).
3862 class LWasmUnarySimd128 : public LInstructionHelper<1, 1, 1> {
3863  public:
3864   LIR_HEADER(WasmUnarySimd128)
3865 
3866   static constexpr uint32_t Src = 0;
3867 
LWasmUnarySimd128(const LAllocation & src,const LDefinition & temp)3868   LWasmUnarySimd128(const LAllocation& src, const LDefinition& temp)
3869       : LInstructionHelper(classOpcode) {
3870     setOperand(Src, src);
3871     setTemp(0, temp);
3872   }
3873 
src()3874   const LAllocation* src() { return getOperand(Src); }
temp()3875   const LDefinition* temp() { return getTemp(0); }
simdOp()3876   wasm::SimdOp simdOp() const { return mir_->toWasmUnarySimd128()->simdOp(); }
3877 };
3878 
3879 // (v128, imm) -> scalar effect-free operations.
3880 // temp is FPR (if in use).
3881 class LWasmReduceSimd128 : public LInstructionHelper<1, 1, 1> {
3882  public:
3883   LIR_HEADER(WasmReduceSimd128)
3884 
3885   static constexpr uint32_t Src = 0;
3886 
LWasmReduceSimd128(const LAllocation & src,const LDefinition & temp)3887   explicit LWasmReduceSimd128(const LAllocation& src, const LDefinition& temp)
3888       : LInstructionHelper(classOpcode) {
3889     setOperand(Src, src);
3890     setTemp(0, temp);
3891   }
3892 
src()3893   const LAllocation* src() { return getOperand(Src); }
imm()3894   uint32_t imm() const { return mir_->toWasmReduceSimd128()->imm(); }
simdOp()3895   wasm::SimdOp simdOp() const { return mir_->toWasmReduceSimd128()->simdOp(); }
3896 };
3897 
3898 // (v128, onTrue, onFalse) test-and-branch operations.
3899 class LWasmReduceAndBranchSimd128 : public LControlInstructionHelper<2, 1, 0> {
3900   wasm::SimdOp op_;
3901 
3902  public:
3903   LIR_HEADER(WasmReduceAndBranchSimd128)
3904 
3905   static constexpr uint32_t Src = 0;
3906   static constexpr uint32_t IfTrue = 0;
3907   static constexpr uint32_t IfFalse = 1;
3908 
LWasmReduceAndBranchSimd128(const LAllocation & src,wasm::SimdOp op,MBasicBlock * ifTrue,MBasicBlock * ifFalse)3909   LWasmReduceAndBranchSimd128(const LAllocation& src, wasm::SimdOp op,
3910                               MBasicBlock* ifTrue, MBasicBlock* ifFalse)
3911       : LControlInstructionHelper(classOpcode), op_(op) {
3912     setOperand(Src, src);
3913     setSuccessor(IfTrue, ifTrue);
3914     setSuccessor(IfFalse, ifFalse);
3915   }
3916 
src()3917   const LAllocation* src() { return getOperand(Src); }
simdOp()3918   wasm::SimdOp simdOp() const { return op_; }
ifTrue()3919   MBasicBlock* ifTrue() const { return getSuccessor(IfTrue); }
ifFalse()3920   MBasicBlock* ifFalse() const { return getSuccessor(IfFalse); }
3921 };
3922 
3923 // (v128, imm) -> i64 effect-free operations
3924 class LWasmReduceSimd128ToInt64
3925     : public LInstructionHelper<INT64_PIECES, 1, 0> {
3926  public:
3927   LIR_HEADER(WasmReduceSimd128ToInt64)
3928 
3929   static constexpr uint32_t Src = 0;
3930 
LWasmReduceSimd128ToInt64(const LAllocation & src)3931   explicit LWasmReduceSimd128ToInt64(const LAllocation& src)
3932       : LInstructionHelper(classOpcode) {
3933     setOperand(Src, src);
3934   }
3935 
src()3936   const LAllocation* src() { return getOperand(Src); }
imm()3937   uint32_t imm() const { return mir_->toWasmReduceSimd128()->imm(); }
simdOp()3938   wasm::SimdOp simdOp() const { return mir_->toWasmReduceSimd128()->simdOp(); }
3939 };
3940 
3941 class LWasmLoadLaneSimd128 : public LInstructionHelper<1, 3, 1> {
3942  public:
3943   LIR_HEADER(WasmLoadLaneSimd128);
3944 
3945   static constexpr uint32_t Src = 2;
3946 
3947   explicit LWasmLoadLaneSimd128(const LAllocation& ptr, const LAllocation& src,
3948                                 const LDefinition& temp,
3949                                 const LAllocation& memoryBase = LAllocation())
LInstructionHelper(classOpcode)3950       : LInstructionHelper(classOpcode) {
3951     setOperand(0, ptr);
3952     setOperand(1, memoryBase);
3953     setOperand(Src, src);
3954     setTemp(0, temp);
3955   }
3956 
ptr()3957   const LAllocation* ptr() { return getOperand(0); }
memoryBase()3958   const LAllocation* memoryBase() { return getOperand(1); }
src()3959   const LAllocation* src() { return getOperand(Src); }
temp()3960   const LDefinition* temp() { return getTemp(0); }
mir()3961   MWasmLoadLaneSimd128* mir() const { return mir_->toWasmLoadLaneSimd128(); }
laneSize()3962   uint32_t laneSize() const {
3963     return mir_->toWasmLoadLaneSimd128()->laneSize();
3964   }
laneIndex()3965   uint32_t laneIndex() const {
3966     return mir_->toWasmLoadLaneSimd128()->laneIndex();
3967   }
3968 };
3969 
3970 class LWasmStoreLaneSimd128 : public LInstructionHelper<1, 3, 1> {
3971  public:
3972   LIR_HEADER(WasmStoreLaneSimd128);
3973 
3974   static constexpr uint32_t Src = 2;
3975 
3976   explicit LWasmStoreLaneSimd128(const LAllocation& ptr, const LAllocation& src,
3977                                  const LDefinition& temp,
3978                                  const LAllocation& memoryBase = LAllocation())
LInstructionHelper(classOpcode)3979       : LInstructionHelper(classOpcode) {
3980     setOperand(0, ptr);
3981     setOperand(1, memoryBase);
3982     setOperand(Src, src);
3983     setTemp(0, temp);
3984   }
3985 
ptr()3986   const LAllocation* ptr() { return getOperand(0); }
memoryBase()3987   const LAllocation* memoryBase() { return getOperand(1); }
src()3988   const LAllocation* src() { return getOperand(Src); }
temp()3989   const LDefinition* temp() { return getTemp(0); }
mir()3990   MWasmStoreLaneSimd128* mir() const { return mir_->toWasmStoreLaneSimd128(); }
laneSize()3991   uint32_t laneSize() const {
3992     return mir_->toWasmStoreLaneSimd128()->laneSize();
3993   }
laneIndex()3994   uint32_t laneIndex() const {
3995     return mir_->toWasmStoreLaneSimd128()->laneIndex();
3996   }
3997 };
3998 
3999 // End Wasm SIMD
4000 
4001 // End Wasm Exception Handling
4002 
4003 }  // namespace jit
4004 }  // namespace js
4005 
4006 #endif /* jit_shared_LIR_shared_h */
4007