1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/arm/CodeGenerator-arm.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,261 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jit_arm_CodeGenerator_arm_h 1.11 +#define jit_arm_CodeGenerator_arm_h 1.12 + 1.13 +#include "jit/arm/Assembler-arm.h" 1.14 +#include "jit/shared/CodeGenerator-shared.h" 1.15 + 1.16 +namespace js { 1.17 +namespace jit { 1.18 + 1.19 +class OutOfLineBailout; 1.20 +class OutOfLineTableSwitch; 1.21 + 1.22 +class CodeGeneratorARM : public CodeGeneratorShared 1.23 +{ 1.24 + friend class MoveResolverARM; 1.25 + 1.26 + CodeGeneratorARM *thisFromCtor() {return this;} 1.27 + 1.28 + protected: 1.29 + // Label for the common return path. 1.30 + NonAssertingLabel returnLabel_; 1.31 + NonAssertingLabel deoptLabel_; 1.32 + // ugh. this is not going to be pretty to move over. 1.33 + // stack slotted variables are not useful on arm. 1.34 + // it looks like this will need to return one of two types. 1.35 + inline Operand ToOperand(const LAllocation &a) { 1.36 + if (a.isGeneralReg()) 1.37 + return Operand(a.toGeneralReg()->reg()); 1.38 + if (a.isFloatReg()) 1.39 + return Operand(a.toFloatReg()->reg()); 1.40 + return Operand(StackPointer, ToStackOffset(&a)); 1.41 + } 1.42 + inline Operand ToOperand(const LAllocation *a) { 1.43 + return ToOperand(*a); 1.44 + } 1.45 + inline Operand ToOperand(const LDefinition *def) { 1.46 + return ToOperand(def->output()); 1.47 + } 1.48 + 1.49 + MoveOperand toMoveOperand(const LAllocation *a) const; 1.50 + 1.51 + bool bailoutIf(Assembler::Condition condition, LSnapshot *snapshot); 1.52 + bool bailoutFrom(Label *label, LSnapshot *snapshot); 1.53 + bool bailout(LSnapshot *snapshot); 1.54 + 1.55 + template <typename T1, typename T2> 1.56 + bool bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) { 1.57 + masm.cmpPtr(lhs, rhs); 1.58 + return bailoutIf(c, snapshot); 1.59 + } 1.60 + bool bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, LSnapshot *snapshot) { 1.61 + masm.testPtr(lhs, rhs); 1.62 + return bailoutIf(c, snapshot); 1.63 + } 1.64 + template <typename T1, typename T2> 1.65 + bool bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) { 1.66 + masm.cmp32(lhs, rhs); 1.67 + return bailoutIf(c, snapshot); 1.68 + } 1.69 + template <typename T1, typename T2> 1.70 + bool bailoutTest32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) { 1.71 + masm.test32(lhs, rhs); 1.72 + return bailoutIf(c, snapshot); 1.73 + } 1.74 + 1.75 + protected: 1.76 + bool generatePrologue(); 1.77 + bool generateAsmJSPrologue(Label *stackOverflowLabel); 1.78 + bool generateEpilogue(); 1.79 + bool generateOutOfLineCode(); 1.80 + 1.81 + void emitRoundDouble(const FloatRegister &src, const Register &dest, Label *fail); 1.82 + 1.83 + // Emits a branch that directs control flow to the true block if |cond| is 1.84 + // true, and the false block if |cond| is false. 1.85 + void emitBranch(Assembler::Condition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse); 1.86 + 1.87 + void testNullEmitBranch(Assembler::Condition cond, const ValueOperand &value, 1.88 + MBasicBlock *ifTrue, MBasicBlock *ifFalse) 1.89 + { 1.90 + cond = masm.testNull(cond, value); 1.91 + emitBranch(cond, ifTrue, ifFalse); 1.92 + } 1.93 + void testUndefinedEmitBranch(Assembler::Condition cond, const ValueOperand &value, 1.94 + MBasicBlock *ifTrue, MBasicBlock *ifFalse) 1.95 + { 1.96 + cond = masm.testUndefined(cond, value); 1.97 + emitBranch(cond, ifTrue, ifFalse); 1.98 + } 1.99 + 1.100 + bool emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, const Register &base); 1.101 + 1.102 + public: 1.103 + // Instruction visitors. 1.104 + virtual bool visitMinMaxD(LMinMaxD *ins); 1.105 + virtual bool visitAbsD(LAbsD *ins); 1.106 + virtual bool visitAbsF(LAbsF *ins); 1.107 + virtual bool visitSqrtD(LSqrtD *ins); 1.108 + virtual bool visitSqrtF(LSqrtF *ins); 1.109 + virtual bool visitAddI(LAddI *ins); 1.110 + virtual bool visitSubI(LSubI *ins); 1.111 + virtual bool visitBitNotI(LBitNotI *ins); 1.112 + virtual bool visitBitOpI(LBitOpI *ins); 1.113 + 1.114 + virtual bool visitMulI(LMulI *ins); 1.115 + 1.116 + virtual bool visitDivI(LDivI *ins); 1.117 + virtual bool visitSoftDivI(LSoftDivI *ins); 1.118 + virtual bool visitDivPowTwoI(LDivPowTwoI *ins); 1.119 + virtual bool visitModI(LModI *ins); 1.120 + virtual bool visitSoftModI(LSoftModI *ins); 1.121 + virtual bool visitModPowTwoI(LModPowTwoI *ins); 1.122 + virtual bool visitModMaskI(LModMaskI *ins); 1.123 + virtual bool visitPowHalfD(LPowHalfD *ins); 1.124 + virtual bool visitShiftI(LShiftI *ins); 1.125 + virtual bool visitUrshD(LUrshD *ins); 1.126 + 1.127 + virtual bool visitTestIAndBranch(LTestIAndBranch *test); 1.128 + virtual bool visitCompare(LCompare *comp); 1.129 + virtual bool visitCompareAndBranch(LCompareAndBranch *comp); 1.130 + virtual bool visitTestDAndBranch(LTestDAndBranch *test); 1.131 + virtual bool visitTestFAndBranch(LTestFAndBranch *test); 1.132 + virtual bool visitCompareD(LCompareD *comp); 1.133 + virtual bool visitCompareF(LCompareF *comp); 1.134 + virtual bool visitCompareDAndBranch(LCompareDAndBranch *comp); 1.135 + virtual bool visitCompareFAndBranch(LCompareFAndBranch *comp); 1.136 + virtual bool visitCompareB(LCompareB *lir); 1.137 + virtual bool visitCompareBAndBranch(LCompareBAndBranch *lir); 1.138 + virtual bool visitCompareV(LCompareV *lir); 1.139 + virtual bool visitCompareVAndBranch(LCompareVAndBranch *lir); 1.140 + virtual bool visitBitAndAndBranch(LBitAndAndBranch *baab); 1.141 + virtual bool visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble *lir); 1.142 + virtual bool visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32 *lir); 1.143 + virtual bool visitNotI(LNotI *ins); 1.144 + virtual bool visitNotD(LNotD *ins); 1.145 + virtual bool visitNotF(LNotF *ins); 1.146 + 1.147 + virtual bool visitMathD(LMathD *math); 1.148 + virtual bool visitMathF(LMathF *math); 1.149 + virtual bool visitFloor(LFloor *lir); 1.150 + virtual bool visitFloorF(LFloorF *lir); 1.151 + virtual bool visitRound(LRound *lir); 1.152 + virtual bool visitRoundF(LRoundF *lir); 1.153 + virtual bool visitTruncateDToInt32(LTruncateDToInt32 *ins); 1.154 + virtual bool visitTruncateFToInt32(LTruncateFToInt32 *ins); 1.155 + 1.156 + // Out of line visitors. 1.157 + bool visitOutOfLineBailout(OutOfLineBailout *ool); 1.158 + bool visitOutOfLineTableSwitch(OutOfLineTableSwitch *ool); 1.159 + 1.160 + protected: 1.161 + ValueOperand ToValue(LInstruction *ins, size_t pos); 1.162 + ValueOperand ToOutValue(LInstruction *ins); 1.163 + ValueOperand ToTempValue(LInstruction *ins, size_t pos); 1.164 + 1.165 + // Functions for LTestVAndBranch. 1.166 + Register splitTagForTest(const ValueOperand &value); 1.167 + 1.168 + void storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType, 1.169 + const Register &elements, const LAllocation *index); 1.170 + 1.171 + bool divICommon(MDiv *mir, Register lhs, Register rhs, Register output, LSnapshot *snapshot, 1.172 + Label &done); 1.173 + bool modICommon(MMod *mir, Register lhs, Register rhs, Register output, LSnapshot *snapshot, 1.174 + Label &done); 1.175 + 1.176 + public: 1.177 + CodeGeneratorARM(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm); 1.178 + 1.179 + public: 1.180 + bool visitBox(LBox *box); 1.181 + bool visitBoxFloatingPoint(LBoxFloatingPoint *box); 1.182 + bool visitUnbox(LUnbox *unbox); 1.183 + bool visitValue(LValue *value); 1.184 + bool visitDouble(LDouble *ins); 1.185 + bool visitFloat32(LFloat32 *ins); 1.186 + 1.187 + bool visitLoadSlotV(LLoadSlotV *load); 1.188 + bool visitLoadSlotT(LLoadSlotT *load); 1.189 + bool visitStoreSlotT(LStoreSlotT *load); 1.190 + 1.191 + bool visitLoadElementT(LLoadElementT *load); 1.192 + 1.193 + bool visitGuardShape(LGuardShape *guard); 1.194 + bool visitGuardObjectType(LGuardObjectType *guard); 1.195 + bool visitGuardClass(LGuardClass *guard); 1.196 + bool visitImplicitThis(LImplicitThis *lir); 1.197 + 1.198 + bool visitInterruptCheck(LInterruptCheck *lir); 1.199 + 1.200 + bool visitNegI(LNegI *lir); 1.201 + bool visitNegD(LNegD *lir); 1.202 + bool visitNegF(LNegF *lir); 1.203 + bool visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic *ins); 1.204 + bool visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic *ins); 1.205 + bool visitAsmJSLoadHeap(LAsmJSLoadHeap *ins); 1.206 + bool visitAsmJSStoreHeap(LAsmJSStoreHeap *ins); 1.207 + bool visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar *ins); 1.208 + bool visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar *ins); 1.209 + bool visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr *ins); 1.210 + bool visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins); 1.211 + bool visitAsmJSPassStackArg(LAsmJSPassStackArg *ins); 1.212 + 1.213 + bool visitForkJoinGetSlice(LForkJoinGetSlice *ins); 1.214 + 1.215 + bool generateInvalidateEpilogue(); 1.216 + protected: 1.217 + void postAsmJSCall(LAsmJSCall *lir) { 1.218 + if (!useHardFpABI() && lir->mir()->callee().which() == MAsmJSCall::Callee::Builtin) { 1.219 + switch (lir->mir()->type()) { 1.220 + case MIRType_Double: 1.221 + masm.ma_vxfer(r0, r1, d0); 1.222 + break; 1.223 + case MIRType_Float32: 1.224 + masm.as_vxfer(r0, InvalidReg, VFPRegister(d0).singleOverlay(), 1.225 + Assembler::CoreToFloat); 1.226 + break; 1.227 + default: 1.228 + break; 1.229 + } 1.230 + } 1.231 + } 1.232 + 1.233 + bool visitEffectiveAddress(LEffectiveAddress *ins); 1.234 + bool visitUDiv(LUDiv *ins); 1.235 + bool visitUMod(LUMod *ins); 1.236 + bool visitSoftUDivOrMod(LSoftUDivOrMod *ins); 1.237 +}; 1.238 + 1.239 +typedef CodeGeneratorARM CodeGeneratorSpecific; 1.240 + 1.241 +// An out-of-line bailout thunk. 1.242 +class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorARM> 1.243 +{ 1.244 + protected: // Silence Clang warning. 1.245 + LSnapshot *snapshot_; 1.246 + uint32_t frameSize_; 1.247 + 1.248 + public: 1.249 + OutOfLineBailout(LSnapshot *snapshot, uint32_t frameSize) 1.250 + : snapshot_(snapshot), 1.251 + frameSize_(frameSize) 1.252 + { } 1.253 + 1.254 + bool accept(CodeGeneratorARM *codegen); 1.255 + 1.256 + LSnapshot *snapshot() const { 1.257 + return snapshot_; 1.258 + } 1.259 +}; 1.260 + 1.261 +} // namespace jit 1.262 +} // namespace js 1.263 + 1.264 +#endif /* jit_arm_CodeGenerator_arm_h */