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_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 #include "js/ScalarType.h" // js::Scalar::Type 13 14 namespace js { 15 namespace jit { 16 17 class CodeGeneratorARM; 18 class OutOfLineBailout; 19 class OutOfLineTableSwitch; 20 21 using OutOfLineWasmTruncateCheck = 22 OutOfLineWasmTruncateCheckBase<CodeGeneratorARM>; 23 24 class CodeGeneratorARM : public CodeGeneratorShared { 25 friend class MoveResolverARM; 26 27 protected: 28 CodeGeneratorARM(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm); 29 30 NonAssertingLabel deoptLabel_; 31 32 MoveOperand toMoveOperand(LAllocation a) const; 33 34 void bailoutIf(Assembler::Condition condition, LSnapshot* snapshot); 35 void bailoutFrom(Label* label, LSnapshot* snapshot); 36 void bailout(LSnapshot* snapshot); 37 38 template <typename T1, typename T2> bailoutCmpPtr(Assembler::Condition c,T1 lhs,T2 rhs,LSnapshot * snapshot)39 void bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, 40 LSnapshot* snapshot) { 41 masm.cmpPtr(lhs, rhs); 42 bailoutIf(c, snapshot); 43 } bailoutTestPtr(Assembler::Condition c,Register lhs,Register rhs,LSnapshot * snapshot)44 void bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, 45 LSnapshot* snapshot) { 46 masm.testPtr(lhs, rhs); 47 bailoutIf(c, snapshot); 48 } 49 template <typename T1, typename T2> bailoutCmp32(Assembler::Condition c,T1 lhs,T2 rhs,LSnapshot * snapshot)50 void bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, 51 LSnapshot* snapshot) { 52 masm.cmp32(lhs, rhs); 53 bailoutIf(c, snapshot); 54 } 55 template <typename T1, typename T2> bailoutTest32(Assembler::Condition c,T1 lhs,T2 rhs,LSnapshot * snapshot)56 void bailoutTest32(Assembler::Condition c, T1 lhs, T2 rhs, 57 LSnapshot* snapshot) { 58 masm.test32(lhs, rhs); 59 bailoutIf(c, snapshot); 60 } bailoutIfFalseBool(Register reg,LSnapshot * snapshot)61 void bailoutIfFalseBool(Register reg, LSnapshot* snapshot) { 62 masm.test32(reg, Imm32(0xFF)); 63 bailoutIf(Assembler::Zero, snapshot); 64 } 65 66 template <class T> 67 void generateUDivModZeroCheck(Register rhs, Register output, Label* done, 68 LSnapshot* snapshot, T* mir); 69 70 bool generateOutOfLineCode(); 71 72 // Emits a branch that directs control flow to the true block if |cond| is 73 // true, and the false block if |cond| is false. 74 void emitBranch(Assembler::Condition cond, MBasicBlock* ifTrue, 75 MBasicBlock* ifFalse); 76 testNullEmitBranch(Assembler::Condition cond,const ValueOperand & value,MBasicBlock * ifTrue,MBasicBlock * ifFalse)77 void testNullEmitBranch(Assembler::Condition cond, const ValueOperand& value, 78 MBasicBlock* ifTrue, MBasicBlock* ifFalse) { 79 cond = masm.testNull(cond, value); 80 emitBranch(cond, ifTrue, ifFalse); 81 } testUndefinedEmitBranch(Assembler::Condition cond,const ValueOperand & value,MBasicBlock * ifTrue,MBasicBlock * ifFalse)82 void testUndefinedEmitBranch(Assembler::Condition cond, 83 const ValueOperand& value, MBasicBlock* ifTrue, 84 MBasicBlock* ifFalse) { 85 cond = masm.testUndefined(cond, value); 86 emitBranch(cond, ifTrue, ifFalse); 87 } testObjectEmitBranch(Assembler::Condition cond,const ValueOperand & value,MBasicBlock * ifTrue,MBasicBlock * ifFalse)88 void testObjectEmitBranch(Assembler::Condition cond, 89 const ValueOperand& value, MBasicBlock* ifTrue, 90 MBasicBlock* ifFalse) { 91 cond = masm.testObject(cond, value); 92 emitBranch(cond, ifTrue, ifFalse); 93 } testZeroEmitBranch(Assembler::Condition cond,Register reg,MBasicBlock * ifTrue,MBasicBlock * ifFalse)94 void testZeroEmitBranch(Assembler::Condition cond, Register reg, 95 MBasicBlock* ifTrue, MBasicBlock* ifFalse) { 96 MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); 97 masm.cmpPtr(reg, ImmWord(0)); 98 emitBranch(cond, ifTrue, ifFalse); 99 } 100 101 void emitTableSwitchDispatch(MTableSwitch* mir, Register index, 102 Register base); 103 104 void emitBigIntDiv(LBigIntDiv* ins, Register dividend, Register divisor, 105 Register output, Label* fail); 106 void emitBigIntMod(LBigIntMod* ins, Register dividend, Register divisor, 107 Register output, Label* fail); 108 109 template <typename T> 110 void emitWasmLoad(T* ins); 111 template <typename T> 112 void emitWasmUnalignedLoad(T* ins); 113 template <typename T> 114 void emitWasmStore(T* ins); 115 template <typename T> 116 void emitWasmUnalignedStore(T* ins); 117 118 ValueOperand ToValue(LInstruction* ins, size_t pos); 119 ValueOperand ToTempValue(LInstruction* ins, size_t pos); 120 121 Register64 ToOperandOrRegister64(const LInt64Allocation input); 122 123 // Functions for LTestVAndBranch. 124 void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag); 125 126 void divICommon(MDiv* mir, Register lhs, Register rhs, Register output, 127 LSnapshot* snapshot, Label& done); 128 void modICommon(MMod* mir, Register lhs, Register rhs, Register output, 129 LSnapshot* snapshot, Label& done); 130 131 void generateInvalidateEpilogue(); 132 133 // Generating a result. 134 template <typename S, typename T> 135 void atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, 136 const S& value, const T& mem, 137 Register flagTemp, Register outTemp, 138 AnyRegister output); 139 140 // Generating no result. 141 template <typename S, typename T> 142 void atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, 143 const S& value, const T& mem, 144 Register flagTemp); 145 146 public: 147 void visitOutOfLineBailout(OutOfLineBailout* ool); 148 void visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool); 149 void visitOutOfLineWasmTruncateCheck(OutOfLineWasmTruncateCheck* ool); 150 }; 151 152 typedef CodeGeneratorARM CodeGeneratorSpecific; 153 154 // An out-of-line bailout thunk. 155 class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorARM> { 156 protected: // Silence Clang warning. 157 LSnapshot* snapshot_; 158 uint32_t frameSize_; 159 160 public: OutOfLineBailout(LSnapshot * snapshot,uint32_t frameSize)161 OutOfLineBailout(LSnapshot* snapshot, uint32_t frameSize) 162 : snapshot_(snapshot), frameSize_(frameSize) {} 163 164 void accept(CodeGeneratorARM* codegen) override; 165 snapshot()166 LSnapshot* snapshot() const { return snapshot_; } 167 }; 168 169 } // namespace jit 170 } // namespace js 171 172 #endif /* jit_arm_CodeGenerator_arm_h */ 173