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_arm64_CodeGenerator_arm64_h 8 #define jit_arm64_CodeGenerator_arm64_h 9 10 #include "jit/arm64/Assembler-arm64.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 CodeGeneratorARM64 : public CodeGeneratorShared 20 { 21 friend class MoveResolverARM64; 22 thisFromCtor()23 CodeGeneratorARM64* thisFromCtor() { return this; } 24 25 public: 26 CodeGeneratorARM64(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm); 27 28 protected: 29 NonAssertingLabel deoptLabel_; 30 31 // FIXME: VIXL Operand does not match the platform-agnostic Operand, 32 // which is just a union of possible arguments. ToOperand(const LAllocation & a)33 inline Operand ToOperand(const LAllocation& a) { 34 MOZ_CRASH("ToOperand"); 35 } ToOperand(const LAllocation * a)36 inline Operand ToOperand(const LAllocation* a) { 37 return ToOperand(*a); 38 } ToOperand(const LDefinition * def)39 inline Operand ToOperand(const LDefinition* def) { 40 return ToOperand(def->output()); 41 } 42 43 MoveOperand toMoveOperand(const LAllocation a) const; 44 45 void bailoutIf(Assembler::Condition condition, LSnapshot* snapshot); 46 void bailoutFrom(Label* label, LSnapshot* snapshot); 47 void bailout(LSnapshot* snapshot); 48 49 template <typename T1, typename T2> bailoutCmpPtr(Assembler::Condition c,T1 lhs,T2 rhs,LSnapshot * snapshot)50 void bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot* snapshot) { 51 masm.cmpPtr(lhs, rhs); 52 return bailoutIf(c, snapshot); 53 } bailoutTestPtr(Assembler::Condition c,Register lhs,Register rhs,LSnapshot * snapshot)54 void bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, LSnapshot* snapshot) { 55 masm.testPtr(lhs, rhs); 56 return bailoutIf(c, snapshot); 57 } 58 template <typename T1, typename T2> bailoutCmp32(Assembler::Condition c,T1 lhs,T2 rhs,LSnapshot * snapshot)59 void bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot* snapshot) { 60 masm.cmp32(lhs, rhs); 61 return bailoutIf(c, snapshot); 62 } 63 template <typename T1, typename T2> bailoutTest32(Assembler::Condition c,T1 lhs,T2 rhs,LSnapshot * snapshot)64 void bailoutTest32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot* snapshot) { 65 masm.test32(lhs, rhs); 66 return bailoutIf(c, snapshot); 67 } bailoutIfFalseBool(Register reg,LSnapshot * snapshot)68 void bailoutIfFalseBool(Register reg, LSnapshot* snapshot) { 69 masm.test32(reg, Imm32(0xFF)); 70 return bailoutIf(Assembler::Zero, snapshot); 71 } 72 73 protected: 74 bool generateOutOfLineCode(); 75 76 void emitRoundDouble(FloatRegister src, Register dest, Label* fail); 77 78 // Emits a branch that directs control flow to the true block if |cond| is 79 // true, and the false block if |cond| is false. 80 void emitBranch(Assembler::Condition cond, MBasicBlock* ifTrue, MBasicBlock* ifFalse); 81 testNullEmitBranch(Assembler::Condition cond,const ValueOperand & value,MBasicBlock * ifTrue,MBasicBlock * ifFalse)82 void testNullEmitBranch(Assembler::Condition cond, const ValueOperand& value, 83 MBasicBlock* ifTrue, MBasicBlock* ifFalse) 84 { 85 cond = masm.testNull(cond, value); 86 emitBranch(cond, ifTrue, ifFalse); 87 } testUndefinedEmitBranch(Assembler::Condition cond,const ValueOperand & value,MBasicBlock * ifTrue,MBasicBlock * ifFalse)88 void testUndefinedEmitBranch(Assembler::Condition cond, const ValueOperand& value, 89 MBasicBlock* ifTrue, MBasicBlock* ifFalse) 90 { 91 cond = masm.testUndefined(cond, value); 92 emitBranch(cond, ifTrue, ifFalse); 93 } testObjectEmitBranch(Assembler::Condition cond,const ValueOperand & value,MBasicBlock * ifTrue,MBasicBlock * ifFalse)94 void testObjectEmitBranch(Assembler::Condition cond, const ValueOperand& value, 95 MBasicBlock* ifTrue, MBasicBlock* ifFalse) 96 { 97 cond = masm.testObject(cond, value); 98 emitBranch(cond, ifTrue, ifFalse); 99 } testZeroEmitBranch(Assembler::Condition cond,Register reg,MBasicBlock * ifTrue,MBasicBlock * ifFalse)100 void testZeroEmitBranch(Assembler::Condition cond, Register reg, 101 MBasicBlock* ifTrue, MBasicBlock* ifFalse) 102 { 103 MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); 104 masm.cmpPtr(reg, ImmWord(0)); 105 emitBranch(cond, ifTrue, ifFalse); 106 } 107 108 void emitTableSwitchDispatch(MTableSwitch* mir, Register index, Register base); 109 110 public: 111 // Instruction visitors. 112 virtual void visitMinMaxD(LMinMaxD* ins); 113 virtual void visitMinMaxF(LMinMaxF* math); 114 virtual void visitAbsD(LAbsD* ins); 115 virtual void visitAbsF(LAbsF* ins); 116 virtual void visitSqrtD(LSqrtD* ins); 117 virtual void visitSqrtF(LSqrtF* ins); 118 virtual void visitAddI(LAddI* ins); 119 virtual void visitSubI(LSubI* ins); 120 virtual void visitBitNotI(LBitNotI* ins); 121 virtual void visitBitOpI(LBitOpI* ins); 122 123 virtual void visitMulI(LMulI* ins); 124 125 virtual void visitDivI(LDivI* ins); 126 virtual void visitDivPowTwoI(LDivPowTwoI* ins); 127 virtual void visitModI(LModI* ins); 128 virtual void visitModPowTwoI(LModPowTwoI* ins); 129 virtual void visitModMaskI(LModMaskI* ins); 130 virtual void visitPowHalfD(LPowHalfD* ins); 131 virtual void visitShiftI(LShiftI* ins); 132 virtual void visitUrshD(LUrshD* ins); 133 134 virtual void visitTestIAndBranch(LTestIAndBranch* test); 135 virtual void visitCompare(LCompare* comp); 136 virtual void visitCompareAndBranch(LCompareAndBranch* comp); 137 virtual void visitTestDAndBranch(LTestDAndBranch* test); 138 virtual void visitTestFAndBranch(LTestFAndBranch* test); 139 virtual void visitCompareD(LCompareD* comp); 140 virtual void visitCompareF(LCompareF* comp); 141 virtual void visitCompareDAndBranch(LCompareDAndBranch* comp); 142 virtual void visitCompareFAndBranch(LCompareFAndBranch* comp); 143 virtual void visitCompareB(LCompareB* lir); 144 virtual void visitCompareBAndBranch(LCompareBAndBranch* lir); 145 virtual void visitCompareBitwise(LCompareBitwise* lir); 146 virtual void visitCompareBitwiseAndBranch(LCompareBitwiseAndBranch* lir); 147 virtual void visitBitAndAndBranch(LBitAndAndBranch* baab); 148 virtual void visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble* lir); 149 virtual void visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32* lir); 150 virtual void visitNotI(LNotI* ins); 151 virtual void visitNotD(LNotD* ins); 152 virtual void visitNotF(LNotF* ins); 153 154 virtual void visitMathD(LMathD* math); 155 virtual void visitMathF(LMathF* math); 156 virtual void visitFloor(LFloor* lir); 157 virtual void visitFloorF(LFloorF* lir); 158 virtual void visitCeil(LCeil* lir); 159 virtual void visitCeilF(LCeilF* lir); 160 virtual void visitRound(LRound* lir); 161 virtual void visitRoundF(LRoundF* lir); 162 virtual void visitTruncateDToInt32(LTruncateDToInt32* ins); 163 virtual void visitTruncateFToInt32(LTruncateFToInt32* ins); 164 165 virtual void visitClzI(LClzI* lir); 166 // Out of line visitors. 167 void visitOutOfLineBailout(OutOfLineBailout* ool); 168 void visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool); 169 170 protected: 171 ValueOperand ToValue(LInstruction* ins, size_t pos); 172 ValueOperand ToOutValue(LInstruction* ins); 173 ValueOperand ToTempValue(LInstruction* ins, size_t pos); 174 175 // Functions for LTestVAndBranch. 176 Register splitTagForTest(const ValueOperand& value); 177 178 void storeElementTyped(const LAllocation* value, MIRType valueType, MIRType elementType, 179 Register elements, const LAllocation* index); 180 181 void divICommon(MDiv* mir, Register lhs, Register rhs, Register output, LSnapshot* snapshot, 182 Label& done); 183 void modICommon(MMod* mir, Register lhs, Register rhs, Register output, LSnapshot* snapshot, 184 Label& done); 185 186 public: 187 void visitBox(LBox* box); 188 void visitUnbox(LUnbox* unbox); 189 void visitValue(LValue* value); 190 void visitDouble(LDouble* ins); 191 void visitFloat32(LFloat32* ins); 192 193 void visitLoadSlotV(LLoadSlotV* load); 194 void visitLoadSlotT(LLoadSlotT* load); 195 void visitStoreSlotT(LStoreSlotT* load); 196 197 void visitLoadElementT(LLoadElementT* load); 198 199 void visitGuardShape(LGuardShape* guard); 200 void visitGuardObjectGroup(LGuardObjectGroup* guard); 201 void visitGuardClass(LGuardClass* guard); 202 203 void visitInterruptCheck(LInterruptCheck* lir); 204 205 void visitNegI(LNegI* lir); 206 void visitNegD(LNegD* lir); 207 void visitNegF(LNegF* lir); 208 void visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins); 209 void visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins); 210 void visitCompareExchangeTypedArrayElement(LCompareExchangeTypedArrayElement* lir); 211 void visitAtomicExchangeTypedArrayElement(LAtomicExchangeTypedArrayElement* lir); 212 void visitAsmJSCall(LAsmJSCall* ins); 213 void visitAsmJSLoadHeap(LAsmJSLoadHeap* ins); 214 void visitAsmJSStoreHeap(LAsmJSStoreHeap* ins); 215 void visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins); 216 void visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap* ins); 217 void visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar* ins); 218 void visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar* ins); 219 void visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr* ins); 220 void visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc* ins); 221 void visitAsmJSPassStackArg(LAsmJSPassStackArg* ins); 222 223 void generateInvalidateEpilogue(); 224 225 void setReturnDoubleRegs(LiveRegisterSet* regs); 226 227 protected: postAsmJSCall(LAsmJSCall * lir)228 void postAsmJSCall(LAsmJSCall* lir) { 229 MOZ_CRASH("postAsmJSCall"); 230 } 231 232 void visitEffectiveAddress(LEffectiveAddress* ins); 233 void visitUDiv(LUDiv* ins); 234 void visitUMod(LUMod* ins); 235 236 public: 237 // Unimplemented SIMD instructions. visitSimdSplatX4(LSimdSplatX4 * lir)238 void visitSimdSplatX4(LSimdSplatX4* lir) { MOZ_CRASH("NYI"); } visitInt32x4(LInt32x4 * ins)239 void visitInt32x4(LInt32x4* ins) { MOZ_CRASH("NYI"); } visitFloat32x4(LFloat32x4 * ins)240 void visitFloat32x4(LFloat32x4* ins) { MOZ_CRASH("NYI"); } visitSimdExtractElementI(LSimdExtractElementI * ins)241 void visitSimdExtractElementI(LSimdExtractElementI* ins) { MOZ_CRASH("NYI"); } visitSimdExtractElementF(LSimdExtractElementF * ins)242 void visitSimdExtractElementF(LSimdExtractElementF* ins) { MOZ_CRASH("NYI"); } visitSimdSignMaskX4(LSimdSignMaskX4 * ins)243 void visitSimdSignMaskX4(LSimdSignMaskX4* ins) { MOZ_CRASH("NYI"); } visitSimdBinaryCompIx4(LSimdBinaryCompIx4 * lir)244 void visitSimdBinaryCompIx4(LSimdBinaryCompIx4* lir) { MOZ_CRASH("NYI"); } visitSimdBinaryCompFx4(LSimdBinaryCompFx4 * lir)245 void visitSimdBinaryCompFx4(LSimdBinaryCompFx4* lir) { MOZ_CRASH("NYI"); } visitSimdBinaryArithIx4(LSimdBinaryArithIx4 * lir)246 void visitSimdBinaryArithIx4(LSimdBinaryArithIx4* lir) { MOZ_CRASH("NYI"); } visitSimdBinaryArithFx4(LSimdBinaryArithFx4 * lir)247 void visitSimdBinaryArithFx4(LSimdBinaryArithFx4* lir) { MOZ_CRASH("NYI"); } visitSimdBinaryBitwiseX4(LSimdBinaryBitwiseX4 * lir)248 void visitSimdBinaryBitwiseX4(LSimdBinaryBitwiseX4* lir) { MOZ_CRASH("NYI"); } 249 }; 250 251 typedef CodeGeneratorARM64 CodeGeneratorSpecific; 252 253 // An out-of-line bailout thunk. 254 class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorARM64> 255 { 256 protected: // Silence Clang warning. 257 LSnapshot* snapshot_; 258 259 public: OutOfLineBailout(LSnapshot * snapshot)260 OutOfLineBailout(LSnapshot* snapshot) 261 : snapshot_(snapshot) 262 { } 263 264 void accept(CodeGeneratorARM64* codegen); 265 snapshot()266 LSnapshot* snapshot() const { 267 return snapshot_; 268 } 269 }; 270 271 } // namespace jit 272 } // namespace js 273 274 #endif /* jit_arm64_CodeGenerator_arm64_h */ 275