|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
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_arm_CodeGenerator_arm_h |
|
8 #define jit_arm_CodeGenerator_arm_h |
|
9 |
|
10 #include "jit/arm/Assembler-arm.h" |
|
11 #include "jit/shared/CodeGenerator-shared.h" |
|
12 |
|
13 namespace js { |
|
14 namespace jit { |
|
15 |
|
16 class OutOfLineBailout; |
|
17 class OutOfLineTableSwitch; |
|
18 |
|
19 class CodeGeneratorARM : public CodeGeneratorShared |
|
20 { |
|
21 friend class MoveResolverARM; |
|
22 |
|
23 CodeGeneratorARM *thisFromCtor() {return this;} |
|
24 |
|
25 protected: |
|
26 // Label for the common return path. |
|
27 NonAssertingLabel returnLabel_; |
|
28 NonAssertingLabel deoptLabel_; |
|
29 // ugh. this is not going to be pretty to move over. |
|
30 // stack slotted variables are not useful on arm. |
|
31 // it looks like this will need to return one of two types. |
|
32 inline Operand ToOperand(const LAllocation &a) { |
|
33 if (a.isGeneralReg()) |
|
34 return Operand(a.toGeneralReg()->reg()); |
|
35 if (a.isFloatReg()) |
|
36 return Operand(a.toFloatReg()->reg()); |
|
37 return Operand(StackPointer, ToStackOffset(&a)); |
|
38 } |
|
39 inline Operand ToOperand(const LAllocation *a) { |
|
40 return ToOperand(*a); |
|
41 } |
|
42 inline Operand ToOperand(const LDefinition *def) { |
|
43 return ToOperand(def->output()); |
|
44 } |
|
45 |
|
46 MoveOperand toMoveOperand(const LAllocation *a) const; |
|
47 |
|
48 bool bailoutIf(Assembler::Condition condition, LSnapshot *snapshot); |
|
49 bool bailoutFrom(Label *label, LSnapshot *snapshot); |
|
50 bool bailout(LSnapshot *snapshot); |
|
51 |
|
52 template <typename T1, typename T2> |
|
53 bool bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) { |
|
54 masm.cmpPtr(lhs, rhs); |
|
55 return bailoutIf(c, snapshot); |
|
56 } |
|
57 bool bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, LSnapshot *snapshot) { |
|
58 masm.testPtr(lhs, rhs); |
|
59 return bailoutIf(c, snapshot); |
|
60 } |
|
61 template <typename T1, typename T2> |
|
62 bool bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) { |
|
63 masm.cmp32(lhs, rhs); |
|
64 return bailoutIf(c, snapshot); |
|
65 } |
|
66 template <typename T1, typename T2> |
|
67 bool bailoutTest32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) { |
|
68 masm.test32(lhs, rhs); |
|
69 return bailoutIf(c, snapshot); |
|
70 } |
|
71 |
|
72 protected: |
|
73 bool generatePrologue(); |
|
74 bool generateAsmJSPrologue(Label *stackOverflowLabel); |
|
75 bool generateEpilogue(); |
|
76 bool generateOutOfLineCode(); |
|
77 |
|
78 void emitRoundDouble(const FloatRegister &src, const Register &dest, Label *fail); |
|
79 |
|
80 // Emits a branch that directs control flow to the true block if |cond| is |
|
81 // true, and the false block if |cond| is false. |
|
82 void emitBranch(Assembler::Condition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse); |
|
83 |
|
84 void testNullEmitBranch(Assembler::Condition cond, const ValueOperand &value, |
|
85 MBasicBlock *ifTrue, MBasicBlock *ifFalse) |
|
86 { |
|
87 cond = masm.testNull(cond, value); |
|
88 emitBranch(cond, ifTrue, ifFalse); |
|
89 } |
|
90 void testUndefinedEmitBranch(Assembler::Condition cond, const ValueOperand &value, |
|
91 MBasicBlock *ifTrue, MBasicBlock *ifFalse) |
|
92 { |
|
93 cond = masm.testUndefined(cond, value); |
|
94 emitBranch(cond, ifTrue, ifFalse); |
|
95 } |
|
96 |
|
97 bool emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, const Register &base); |
|
98 |
|
99 public: |
|
100 // Instruction visitors. |
|
101 virtual bool visitMinMaxD(LMinMaxD *ins); |
|
102 virtual bool visitAbsD(LAbsD *ins); |
|
103 virtual bool visitAbsF(LAbsF *ins); |
|
104 virtual bool visitSqrtD(LSqrtD *ins); |
|
105 virtual bool visitSqrtF(LSqrtF *ins); |
|
106 virtual bool visitAddI(LAddI *ins); |
|
107 virtual bool visitSubI(LSubI *ins); |
|
108 virtual bool visitBitNotI(LBitNotI *ins); |
|
109 virtual bool visitBitOpI(LBitOpI *ins); |
|
110 |
|
111 virtual bool visitMulI(LMulI *ins); |
|
112 |
|
113 virtual bool visitDivI(LDivI *ins); |
|
114 virtual bool visitSoftDivI(LSoftDivI *ins); |
|
115 virtual bool visitDivPowTwoI(LDivPowTwoI *ins); |
|
116 virtual bool visitModI(LModI *ins); |
|
117 virtual bool visitSoftModI(LSoftModI *ins); |
|
118 virtual bool visitModPowTwoI(LModPowTwoI *ins); |
|
119 virtual bool visitModMaskI(LModMaskI *ins); |
|
120 virtual bool visitPowHalfD(LPowHalfD *ins); |
|
121 virtual bool visitShiftI(LShiftI *ins); |
|
122 virtual bool visitUrshD(LUrshD *ins); |
|
123 |
|
124 virtual bool visitTestIAndBranch(LTestIAndBranch *test); |
|
125 virtual bool visitCompare(LCompare *comp); |
|
126 virtual bool visitCompareAndBranch(LCompareAndBranch *comp); |
|
127 virtual bool visitTestDAndBranch(LTestDAndBranch *test); |
|
128 virtual bool visitTestFAndBranch(LTestFAndBranch *test); |
|
129 virtual bool visitCompareD(LCompareD *comp); |
|
130 virtual bool visitCompareF(LCompareF *comp); |
|
131 virtual bool visitCompareDAndBranch(LCompareDAndBranch *comp); |
|
132 virtual bool visitCompareFAndBranch(LCompareFAndBranch *comp); |
|
133 virtual bool visitCompareB(LCompareB *lir); |
|
134 virtual bool visitCompareBAndBranch(LCompareBAndBranch *lir); |
|
135 virtual bool visitCompareV(LCompareV *lir); |
|
136 virtual bool visitCompareVAndBranch(LCompareVAndBranch *lir); |
|
137 virtual bool visitBitAndAndBranch(LBitAndAndBranch *baab); |
|
138 virtual bool visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble *lir); |
|
139 virtual bool visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32 *lir); |
|
140 virtual bool visitNotI(LNotI *ins); |
|
141 virtual bool visitNotD(LNotD *ins); |
|
142 virtual bool visitNotF(LNotF *ins); |
|
143 |
|
144 virtual bool visitMathD(LMathD *math); |
|
145 virtual bool visitMathF(LMathF *math); |
|
146 virtual bool visitFloor(LFloor *lir); |
|
147 virtual bool visitFloorF(LFloorF *lir); |
|
148 virtual bool visitRound(LRound *lir); |
|
149 virtual bool visitRoundF(LRoundF *lir); |
|
150 virtual bool visitTruncateDToInt32(LTruncateDToInt32 *ins); |
|
151 virtual bool visitTruncateFToInt32(LTruncateFToInt32 *ins); |
|
152 |
|
153 // Out of line visitors. |
|
154 bool visitOutOfLineBailout(OutOfLineBailout *ool); |
|
155 bool visitOutOfLineTableSwitch(OutOfLineTableSwitch *ool); |
|
156 |
|
157 protected: |
|
158 ValueOperand ToValue(LInstruction *ins, size_t pos); |
|
159 ValueOperand ToOutValue(LInstruction *ins); |
|
160 ValueOperand ToTempValue(LInstruction *ins, size_t pos); |
|
161 |
|
162 // Functions for LTestVAndBranch. |
|
163 Register splitTagForTest(const ValueOperand &value); |
|
164 |
|
165 void storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType, |
|
166 const Register &elements, const LAllocation *index); |
|
167 |
|
168 bool divICommon(MDiv *mir, Register lhs, Register rhs, Register output, LSnapshot *snapshot, |
|
169 Label &done); |
|
170 bool modICommon(MMod *mir, Register lhs, Register rhs, Register output, LSnapshot *snapshot, |
|
171 Label &done); |
|
172 |
|
173 public: |
|
174 CodeGeneratorARM(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm); |
|
175 |
|
176 public: |
|
177 bool visitBox(LBox *box); |
|
178 bool visitBoxFloatingPoint(LBoxFloatingPoint *box); |
|
179 bool visitUnbox(LUnbox *unbox); |
|
180 bool visitValue(LValue *value); |
|
181 bool visitDouble(LDouble *ins); |
|
182 bool visitFloat32(LFloat32 *ins); |
|
183 |
|
184 bool visitLoadSlotV(LLoadSlotV *load); |
|
185 bool visitLoadSlotT(LLoadSlotT *load); |
|
186 bool visitStoreSlotT(LStoreSlotT *load); |
|
187 |
|
188 bool visitLoadElementT(LLoadElementT *load); |
|
189 |
|
190 bool visitGuardShape(LGuardShape *guard); |
|
191 bool visitGuardObjectType(LGuardObjectType *guard); |
|
192 bool visitGuardClass(LGuardClass *guard); |
|
193 bool visitImplicitThis(LImplicitThis *lir); |
|
194 |
|
195 bool visitInterruptCheck(LInterruptCheck *lir); |
|
196 |
|
197 bool visitNegI(LNegI *lir); |
|
198 bool visitNegD(LNegD *lir); |
|
199 bool visitNegF(LNegF *lir); |
|
200 bool visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic *ins); |
|
201 bool visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic *ins); |
|
202 bool visitAsmJSLoadHeap(LAsmJSLoadHeap *ins); |
|
203 bool visitAsmJSStoreHeap(LAsmJSStoreHeap *ins); |
|
204 bool visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar *ins); |
|
205 bool visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar *ins); |
|
206 bool visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr *ins); |
|
207 bool visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins); |
|
208 bool visitAsmJSPassStackArg(LAsmJSPassStackArg *ins); |
|
209 |
|
210 bool visitForkJoinGetSlice(LForkJoinGetSlice *ins); |
|
211 |
|
212 bool generateInvalidateEpilogue(); |
|
213 protected: |
|
214 void postAsmJSCall(LAsmJSCall *lir) { |
|
215 if (!useHardFpABI() && lir->mir()->callee().which() == MAsmJSCall::Callee::Builtin) { |
|
216 switch (lir->mir()->type()) { |
|
217 case MIRType_Double: |
|
218 masm.ma_vxfer(r0, r1, d0); |
|
219 break; |
|
220 case MIRType_Float32: |
|
221 masm.as_vxfer(r0, InvalidReg, VFPRegister(d0).singleOverlay(), |
|
222 Assembler::CoreToFloat); |
|
223 break; |
|
224 default: |
|
225 break; |
|
226 } |
|
227 } |
|
228 } |
|
229 |
|
230 bool visitEffectiveAddress(LEffectiveAddress *ins); |
|
231 bool visitUDiv(LUDiv *ins); |
|
232 bool visitUMod(LUMod *ins); |
|
233 bool visitSoftUDivOrMod(LSoftUDivOrMod *ins); |
|
234 }; |
|
235 |
|
236 typedef CodeGeneratorARM CodeGeneratorSpecific; |
|
237 |
|
238 // An out-of-line bailout thunk. |
|
239 class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorARM> |
|
240 { |
|
241 protected: // Silence Clang warning. |
|
242 LSnapshot *snapshot_; |
|
243 uint32_t frameSize_; |
|
244 |
|
245 public: |
|
246 OutOfLineBailout(LSnapshot *snapshot, uint32_t frameSize) |
|
247 : snapshot_(snapshot), |
|
248 frameSize_(frameSize) |
|
249 { } |
|
250 |
|
251 bool accept(CodeGeneratorARM *codegen); |
|
252 |
|
253 LSnapshot *snapshot() const { |
|
254 return snapshot_; |
|
255 } |
|
256 }; |
|
257 |
|
258 } // namespace jit |
|
259 } // namespace js |
|
260 |
|
261 #endif /* jit_arm_CodeGenerator_arm_h */ |