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_x64_LIR_x64_h
8 #define jit_x64_LIR_x64_h
9 
10 namespace js {
11 namespace jit {
12 
13 // Given an untyped input, guards on whether it's a specific type and returns
14 // the unboxed payload.
15 class LUnboxBase : public LInstructionHelper<1, 1, 0> {
16  public:
LUnboxBase(LNode::Opcode op,const LAllocation & input)17   LUnboxBase(LNode::Opcode op, const LAllocation& input)
18       : LInstructionHelper<1, 1, 0>(op) {
19     setOperand(0, input);
20   }
21 
22   static const size_t Input = 0;
23 
mir()24   MUnbox* mir() const { return mir_->toUnbox(); }
25 };
26 
27 class LUnbox : public LUnboxBase {
28  public:
LIR_HEADER(Unbox)29   LIR_HEADER(Unbox)
30 
31   explicit LUnbox(const LAllocation& input) : LUnboxBase(classOpcode, input) {}
32 
extraName()33   const char* extraName() const { return StringFromMIRType(mir()->type()); }
34 };
35 
36 class LUnboxFloatingPoint : public LUnboxBase {
37   MIRType type_;
38 
39  public:
LIR_HEADER(UnboxFloatingPoint)40   LIR_HEADER(UnboxFloatingPoint)
41 
42   LUnboxFloatingPoint(const LAllocation& input, MIRType type)
43       : LUnboxBase(classOpcode, input), type_(type) {}
44 
type()45   MIRType type() const { return type_; }
extraName()46   const char* extraName() const { return StringFromMIRType(type_); }
47 };
48 
49 // Convert a 32-bit unsigned integer to a double.
50 class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0> {
51  public:
LIR_HEADER(WasmUint32ToDouble)52   LIR_HEADER(WasmUint32ToDouble)
53 
54   explicit LWasmUint32ToDouble(const LAllocation& input)
55       : LInstructionHelper(classOpcode) {
56     setOperand(0, input);
57   }
58 };
59 
60 // Convert a 32-bit unsigned integer to a float32.
61 class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0> {
62  public:
LIR_HEADER(WasmUint32ToFloat32)63   LIR_HEADER(WasmUint32ToFloat32)
64 
65   explicit LWasmUint32ToFloat32(const LAllocation& input)
66       : LInstructionHelper(classOpcode) {
67     setOperand(0, input);
68   }
69 };
70 
71 class LDivOrModI64 : public LBinaryMath<1> {
72  public:
LIR_HEADER(DivOrModI64)73   LIR_HEADER(DivOrModI64)
74 
75   LDivOrModI64(const LAllocation& lhs, const LAllocation& rhs,
76                const LDefinition& temp)
77       : LBinaryMath(classOpcode) {
78     setOperand(0, lhs);
79     setOperand(1, rhs);
80     setTemp(0, temp);
81   }
82 
remainder()83   const LDefinition* remainder() { return getTemp(0); }
84 
mir()85   MBinaryArithInstruction* mir() const {
86     MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
87     return static_cast<MBinaryArithInstruction*>(mir_);
88   }
canBeDivideByZero()89   bool canBeDivideByZero() const {
90     if (mir_->isMod()) {
91       return mir_->toMod()->canBeDivideByZero();
92     }
93     return mir_->toDiv()->canBeDivideByZero();
94   }
canBeNegativeOverflow()95   bool canBeNegativeOverflow() const {
96     if (mir_->isMod()) {
97       return mir_->toMod()->canBeNegativeDividend();
98     }
99     return mir_->toDiv()->canBeNegativeOverflow();
100   }
bytecodeOffset()101   wasm::BytecodeOffset bytecodeOffset() const {
102     MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
103     if (mir_->isMod()) {
104       return mir_->toMod()->bytecodeOffset();
105     }
106     return mir_->toDiv()->bytecodeOffset();
107   }
108 };
109 
110 // This class performs a simple x86 'div', yielding either a quotient or
111 // remainder depending on whether this instruction is defined to output
112 // rax (quotient) or rdx (remainder).
113 class LUDivOrModI64 : public LBinaryMath<1> {
114  public:
115   LIR_HEADER(UDivOrModI64);
116 
LUDivOrModI64(const LAllocation & lhs,const LAllocation & rhs,const LDefinition & temp)117   LUDivOrModI64(const LAllocation& lhs, const LAllocation& rhs,
118                 const LDefinition& temp)
119       : LBinaryMath(classOpcode) {
120     setOperand(0, lhs);
121     setOperand(1, rhs);
122     setTemp(0, temp);
123   }
124 
remainder()125   const LDefinition* remainder() { return getTemp(0); }
126 
extraName()127   const char* extraName() const {
128     return mir()->isTruncated() ? "Truncated" : nullptr;
129   }
130 
mir()131   MBinaryArithInstruction* mir() const {
132     MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
133     return static_cast<MBinaryArithInstruction*>(mir_);
134   }
135 
canBeDivideByZero()136   bool canBeDivideByZero() const {
137     if (mir_->isMod()) {
138       return mir_->toMod()->canBeDivideByZero();
139     }
140     return mir_->toDiv()->canBeDivideByZero();
141   }
142 
bytecodeOffset()143   wasm::BytecodeOffset bytecodeOffset() const {
144     MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
145     if (mir_->isMod()) {
146       return mir_->toMod()->bytecodeOffset();
147     }
148     return mir_->toDiv()->bytecodeOffset();
149   }
150 };
151 
152 class LWasmTruncateToInt64 : public LInstructionHelper<1, 1, 1> {
153  public:
154   LIR_HEADER(WasmTruncateToInt64);
155 
LWasmTruncateToInt64(const LAllocation & in,const LDefinition & temp)156   LWasmTruncateToInt64(const LAllocation& in, const LDefinition& temp)
157       : LInstructionHelper(classOpcode) {
158     setOperand(0, in);
159     setTemp(0, temp);
160   }
161 
mir()162   MWasmTruncateToInt64* mir() const { return mir_->toWasmTruncateToInt64(); }
163 
temp()164   const LDefinition* temp() { return getTemp(0); }
165 };
166 
167 }  // namespace jit
168 }  // namespace js
169 
170 #endif /* jit_x64_LIR_x64_h */
171