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_x86_shared_CodeGenerator_x86_shared_h 8 #define jit_x86_shared_CodeGenerator_x86_shared_h 9 10 #include "jit/shared/CodeGenerator-shared.h" 11 #include "js/ScalarType.h" // js::Scalar::Type 12 13 namespace js { 14 namespace jit { 15 16 class CodeGeneratorX86Shared; 17 class OutOfLineBailout; 18 class OutOfLineUndoALUOperation; 19 class OutOfLineLoadTypedArrayOutOfBounds; 20 class MulNegativeZeroCheck; 21 class ModOverflowCheck; 22 class ReturnZero; 23 class OutOfLineTableSwitch; 24 25 using OutOfLineWasmTruncateCheck = 26 OutOfLineWasmTruncateCheckBase<CodeGeneratorX86Shared>; 27 28 class CodeGeneratorX86Shared : public CodeGeneratorShared { 29 friend class MoveResolverX86; 30 31 template <typename T> 32 void bailout(const T& t, LSnapshot* snapshot); 33 34 protected: 35 CodeGeneratorX86Shared(MIRGenerator* gen, LIRGraph* graph, 36 MacroAssembler* masm); 37 38 // Load a NaN or zero into a register for an out of bounds AsmJS or static 39 // typed array load. 40 class OutOfLineLoadTypedArrayOutOfBounds 41 : public OutOfLineCodeBase<CodeGeneratorX86Shared> { 42 AnyRegister dest_; 43 Scalar::Type viewType_; 44 45 public: OutOfLineLoadTypedArrayOutOfBounds(AnyRegister dest,Scalar::Type viewType)46 OutOfLineLoadTypedArrayOutOfBounds(AnyRegister dest, Scalar::Type viewType) 47 : dest_(dest), viewType_(viewType) {} 48 dest()49 AnyRegister dest() const { return dest_; } viewType()50 Scalar::Type viewType() const { return viewType_; } accept(CodeGeneratorX86Shared * codegen)51 void accept(CodeGeneratorX86Shared* codegen) override { 52 codegen->visitOutOfLineLoadTypedArrayOutOfBounds(this); 53 } 54 }; 55 56 NonAssertingLabel deoptLabel_; 57 58 Operand ToOperand(const LAllocation& a); 59 Operand ToOperand(const LAllocation* a); 60 Operand ToOperand(const LDefinition* def); 61 62 #ifdef JS_PUNBOX64 63 Operand ToOperandOrRegister64(const LInt64Allocation input); 64 #else 65 Register64 ToOperandOrRegister64(const LInt64Allocation input); 66 #endif 67 68 MoveOperand toMoveOperand(LAllocation a) const; 69 70 void bailoutIf(Assembler::Condition condition, LSnapshot* snapshot); 71 void bailoutIf(Assembler::DoubleCondition condition, LSnapshot* snapshot); 72 void bailoutFrom(Label* label, LSnapshot* snapshot); 73 void bailout(LSnapshot* snapshot); 74 75 template <typename T1, typename T2> bailoutCmpPtr(Assembler::Condition c,T1 lhs,T2 rhs,LSnapshot * snapshot)76 void bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, 77 LSnapshot* snapshot) { 78 masm.cmpPtr(lhs, rhs); 79 bailoutIf(c, snapshot); 80 } bailoutTestPtr(Assembler::Condition c,Register lhs,Register rhs,LSnapshot * snapshot)81 void bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, 82 LSnapshot* snapshot) { 83 masm.testPtr(lhs, rhs); 84 bailoutIf(c, snapshot); 85 } 86 template <typename T1, typename T2> bailoutCmp32(Assembler::Condition c,T1 lhs,T2 rhs,LSnapshot * snapshot)87 void bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, 88 LSnapshot* snapshot) { 89 masm.cmp32(lhs, rhs); 90 bailoutIf(c, snapshot); 91 } 92 template <typename T1, typename T2> bailoutTest32(Assembler::Condition c,T1 lhs,T2 rhs,LSnapshot * snapshot)93 void bailoutTest32(Assembler::Condition c, T1 lhs, T2 rhs, 94 LSnapshot* snapshot) { 95 masm.test32(lhs, rhs); 96 bailoutIf(c, snapshot); 97 } bailoutIfFalseBool(Register reg,LSnapshot * snapshot)98 void bailoutIfFalseBool(Register reg, LSnapshot* snapshot) { 99 masm.test32(reg, Imm32(0xFF)); 100 bailoutIf(Assembler::Zero, snapshot); 101 } bailoutCvttsd2si(FloatRegister src,Register dest,LSnapshot * snapshot)102 void bailoutCvttsd2si(FloatRegister src, Register dest, LSnapshot* snapshot) { 103 Label bail; 104 masm.truncateDoubleToInt32(src, dest, &bail); 105 bailoutFrom(&bail, snapshot); 106 } bailoutCvttss2si(FloatRegister src,Register dest,LSnapshot * snapshot)107 void bailoutCvttss2si(FloatRegister src, Register dest, LSnapshot* snapshot) { 108 Label bail; 109 masm.truncateFloat32ToInt32(src, dest, &bail); 110 bailoutFrom(&bail, snapshot); 111 } 112 113 bool generateOutOfLineCode(); 114 115 void emitCompare(MCompare::CompareType type, const LAllocation* left, 116 const LAllocation* right); 117 118 // Emits a branch that directs control flow to the true block if |cond| is 119 // true, and the false block if |cond| is false. 120 void emitBranch(Assembler::Condition cond, MBasicBlock* ifTrue, 121 MBasicBlock* ifFalse, 122 Assembler::NaNCond ifNaN = Assembler::NaN_HandledByCond); 123 void emitBranch(Assembler::DoubleCondition cond, MBasicBlock* ifTrue, 124 MBasicBlock* ifFalse); 125 testNullEmitBranch(Assembler::Condition cond,const ValueOperand & value,MBasicBlock * ifTrue,MBasicBlock * ifFalse)126 void testNullEmitBranch(Assembler::Condition cond, const ValueOperand& value, 127 MBasicBlock* ifTrue, MBasicBlock* ifFalse) { 128 cond = masm.testNull(cond, value); 129 emitBranch(cond, ifTrue, ifFalse); 130 } testUndefinedEmitBranch(Assembler::Condition cond,const ValueOperand & value,MBasicBlock * ifTrue,MBasicBlock * ifFalse)131 void testUndefinedEmitBranch(Assembler::Condition cond, 132 const ValueOperand& value, MBasicBlock* ifTrue, 133 MBasicBlock* ifFalse) { 134 cond = masm.testUndefined(cond, value); 135 emitBranch(cond, ifTrue, ifFalse); 136 } testObjectEmitBranch(Assembler::Condition cond,const ValueOperand & value,MBasicBlock * ifTrue,MBasicBlock * ifFalse)137 void testObjectEmitBranch(Assembler::Condition cond, 138 const ValueOperand& value, MBasicBlock* ifTrue, 139 MBasicBlock* ifFalse) { 140 cond = masm.testObject(cond, value); 141 emitBranch(cond, ifTrue, ifFalse); 142 } 143 testZeroEmitBranch(Assembler::Condition cond,Register reg,MBasicBlock * ifTrue,MBasicBlock * ifFalse)144 void testZeroEmitBranch(Assembler::Condition cond, Register reg, 145 MBasicBlock* ifTrue, MBasicBlock* ifFalse) { 146 MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); 147 masm.cmpPtr(reg, ImmWord(0)); 148 emitBranch(cond, ifTrue, ifFalse); 149 } 150 151 void emitTableSwitchDispatch(MTableSwitch* mir, Register index, 152 Register base); 153 154 void generateInvalidateEpilogue(); 155 156 void canonicalizeIfDeterministic(Scalar::Type type, const LAllocation* value); 157 158 template <typename T> 159 Operand toMemoryAccessOperand(T* lir, int32_t disp); 160 161 public: 162 // Out of line visitors. 163 void visitOutOfLineBailout(OutOfLineBailout* ool); 164 void visitOutOfLineUndoALUOperation(OutOfLineUndoALUOperation* ool); 165 void visitMulNegativeZeroCheck(MulNegativeZeroCheck* ool); 166 void visitModOverflowCheck(ModOverflowCheck* ool); 167 void visitReturnZero(ReturnZero* ool); 168 void visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool); 169 void visitOutOfLineLoadTypedArrayOutOfBounds( 170 OutOfLineLoadTypedArrayOutOfBounds* ool); 171 void visitOutOfLineWasmTruncateCheck(OutOfLineWasmTruncateCheck* ool); 172 }; 173 174 // An out-of-line bailout thunk. 175 class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorX86Shared> { 176 LSnapshot* snapshot_; 177 178 public: OutOfLineBailout(LSnapshot * snapshot)179 explicit OutOfLineBailout(LSnapshot* snapshot) : snapshot_(snapshot) {} 180 181 void accept(CodeGeneratorX86Shared* codegen) override; 182 snapshot()183 LSnapshot* snapshot() const { return snapshot_; } 184 }; 185 186 } // namespace jit 187 } // namespace js 188 189 #endif /* jit_x86_shared_CodeGenerator_x86_shared_h */ 190