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