michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef jit_shared_CodeGenerator_x86_shared_h michael@0: #define jit_shared_CodeGenerator_x86_shared_h michael@0: michael@0: #include "jit/shared/CodeGenerator-shared.h" michael@0: michael@0: namespace js { michael@0: namespace jit { michael@0: michael@0: class OutOfLineBailout; michael@0: class OutOfLineUndoALUOperation; michael@0: class MulNegativeZeroCheck; michael@0: class ModOverflowCheck; michael@0: class ReturnZero; michael@0: class OutOfLineTableSwitch; michael@0: michael@0: class CodeGeneratorX86Shared : public CodeGeneratorShared michael@0: { michael@0: friend class MoveResolverX86; michael@0: michael@0: CodeGeneratorX86Shared *thisFromCtor() { michael@0: return this; michael@0: } michael@0: michael@0: template michael@0: bool bailout(const T &t, LSnapshot *snapshot); michael@0: michael@0: protected: michael@0: // Label for the common return path. michael@0: NonAssertingLabel returnLabel_; michael@0: NonAssertingLabel deoptLabel_; michael@0: michael@0: inline Operand ToOperand(const LAllocation &a) { michael@0: if (a.isGeneralReg()) michael@0: return Operand(a.toGeneralReg()->reg()); michael@0: if (a.isFloatReg()) michael@0: return Operand(a.toFloatReg()->reg()); michael@0: return Operand(StackPointer, ToStackOffset(&a)); michael@0: } michael@0: inline Operand ToOperand(const LAllocation *a) { michael@0: return ToOperand(*a); michael@0: } michael@0: inline Operand ToOperand(const LDefinition *def) { michael@0: return ToOperand(def->output()); michael@0: } michael@0: michael@0: MoveOperand toMoveOperand(const LAllocation *a) const; michael@0: michael@0: bool bailoutIf(Assembler::Condition condition, LSnapshot *snapshot); michael@0: bool bailoutIf(Assembler::DoubleCondition condition, LSnapshot *snapshot); michael@0: bool bailoutFrom(Label *label, LSnapshot *snapshot); michael@0: bool bailout(LSnapshot *snapshot); michael@0: michael@0: template michael@0: bool bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) { michael@0: masm.cmpPtr(lhs, rhs); michael@0: return bailoutIf(c, snapshot); michael@0: } michael@0: bool bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, LSnapshot *snapshot) { michael@0: masm.testPtr(lhs, rhs); michael@0: return bailoutIf(c, snapshot); michael@0: } michael@0: template michael@0: bool bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) { michael@0: masm.cmp32(lhs, rhs); michael@0: return bailoutIf(c, snapshot); michael@0: } michael@0: template michael@0: bool bailoutTest32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) { michael@0: masm.test32(lhs, rhs); michael@0: return bailoutIf(c, snapshot); michael@0: } michael@0: michael@0: protected: michael@0: bool generatePrologue(); michael@0: bool generateAsmJSPrologue(Label *stackOverflowLabe); michael@0: bool generateEpilogue(); michael@0: bool generateOutOfLineCode(); michael@0: michael@0: Operand createArrayElementOperand(Register elements, const LAllocation *index); michael@0: michael@0: void emitCompare(MCompare::CompareType type, const LAllocation *left, const LAllocation *right); michael@0: michael@0: // Emits a branch that directs control flow to the true block if |cond| is michael@0: // true, and the false block if |cond| is false. michael@0: void emitBranch(Assembler::Condition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse, michael@0: Assembler::NaNCond ifNaN = Assembler::NaN_HandledByCond); michael@0: void emitBranch(Assembler::DoubleCondition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse); michael@0: michael@0: void testNullEmitBranch(Assembler::Condition cond, const ValueOperand &value, michael@0: MBasicBlock *ifTrue, MBasicBlock *ifFalse) michael@0: { michael@0: cond = masm.testNull(cond, value); michael@0: emitBranch(cond, ifTrue, ifFalse); michael@0: } michael@0: void testUndefinedEmitBranch(Assembler::Condition cond, const ValueOperand &value, michael@0: MBasicBlock *ifTrue, MBasicBlock *ifFalse) michael@0: { michael@0: cond = masm.testUndefined(cond, value); michael@0: emitBranch(cond, ifTrue, ifFalse); michael@0: } michael@0: michael@0: bool emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, const Register &base); michael@0: michael@0: public: michael@0: CodeGeneratorX86Shared(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm); michael@0: michael@0: public: michael@0: // Instruction visitors. michael@0: virtual bool visitDouble(LDouble *ins); michael@0: virtual bool visitFloat32(LFloat32 *ins); michael@0: virtual bool visitMinMaxD(LMinMaxD *ins); michael@0: virtual bool visitAbsD(LAbsD *ins); michael@0: virtual bool visitAbsF(LAbsF *ins); michael@0: virtual bool visitSqrtD(LSqrtD *ins); michael@0: virtual bool visitSqrtF(LSqrtF *ins); michael@0: virtual bool visitPowHalfD(LPowHalfD *ins); michael@0: virtual bool visitAddI(LAddI *ins); michael@0: virtual bool visitSubI(LSubI *ins); michael@0: virtual bool visitMulI(LMulI *ins); michael@0: virtual bool visitDivI(LDivI *ins); michael@0: virtual bool visitDivPowTwoI(LDivPowTwoI *ins); michael@0: virtual bool visitDivOrModConstantI(LDivOrModConstantI *ins); michael@0: virtual bool visitModI(LModI *ins); michael@0: virtual bool visitModPowTwoI(LModPowTwoI *ins); michael@0: virtual bool visitBitNotI(LBitNotI *ins); michael@0: virtual bool visitBitOpI(LBitOpI *ins); michael@0: virtual bool visitShiftI(LShiftI *ins); michael@0: virtual bool visitUrshD(LUrshD *ins); michael@0: virtual bool visitTestIAndBranch(LTestIAndBranch *test); michael@0: virtual bool visitTestDAndBranch(LTestDAndBranch *test); michael@0: virtual bool visitTestFAndBranch(LTestFAndBranch *test); michael@0: virtual bool visitCompare(LCompare *comp); michael@0: virtual bool visitCompareAndBranch(LCompareAndBranch *comp); michael@0: virtual bool visitCompareD(LCompareD *comp); michael@0: virtual bool visitCompareDAndBranch(LCompareDAndBranch *comp); michael@0: virtual bool visitCompareF(LCompareF *comp); michael@0: virtual bool visitCompareFAndBranch(LCompareFAndBranch *comp); michael@0: virtual bool visitBitAndAndBranch(LBitAndAndBranch *baab); michael@0: virtual bool visitNotI(LNotI *comp); michael@0: virtual bool visitNotD(LNotD *comp); michael@0: virtual bool visitNotF(LNotF *comp); michael@0: virtual bool visitMathD(LMathD *math); michael@0: virtual bool visitMathF(LMathF *math); michael@0: virtual bool visitFloor(LFloor *lir); michael@0: virtual bool visitFloorF(LFloorF *lir); michael@0: virtual bool visitRound(LRound *lir); michael@0: virtual bool visitRoundF(LRoundF *lir); michael@0: virtual bool visitGuardShape(LGuardShape *guard); michael@0: virtual bool visitGuardObjectType(LGuardObjectType *guard); michael@0: virtual bool visitGuardClass(LGuardClass *guard); michael@0: virtual bool visitEffectiveAddress(LEffectiveAddress *ins); michael@0: virtual bool visitUDivOrMod(LUDivOrMod *ins); michael@0: virtual bool visitAsmJSPassStackArg(LAsmJSPassStackArg *ins); michael@0: michael@0: bool visitForkJoinGetSlice(LForkJoinGetSlice *ins); michael@0: michael@0: bool visitNegI(LNegI *lir); michael@0: bool visitNegD(LNegD *lir); michael@0: bool visitNegF(LNegF *lir); michael@0: michael@0: // Out of line visitors. michael@0: bool visitOutOfLineBailout(OutOfLineBailout *ool); michael@0: bool visitOutOfLineUndoALUOperation(OutOfLineUndoALUOperation *ool); michael@0: bool visitMulNegativeZeroCheck(MulNegativeZeroCheck *ool); michael@0: bool visitModOverflowCheck(ModOverflowCheck *ool); michael@0: bool visitReturnZero(ReturnZero *ool); michael@0: bool visitOutOfLineTableSwitch(OutOfLineTableSwitch *ool); michael@0: bool generateInvalidateEpilogue(); michael@0: }; michael@0: michael@0: // An out-of-line bailout thunk. michael@0: class OutOfLineBailout : public OutOfLineCodeBase michael@0: { michael@0: LSnapshot *snapshot_; michael@0: michael@0: public: michael@0: OutOfLineBailout(LSnapshot *snapshot) michael@0: : snapshot_(snapshot) michael@0: { } michael@0: michael@0: bool accept(CodeGeneratorX86Shared *codegen); michael@0: michael@0: LSnapshot *snapshot() const { michael@0: return snapshot_; michael@0: } michael@0: }; michael@0: michael@0: } // namespace jit michael@0: } // namespace js michael@0: michael@0: #endif /* jit_shared_CodeGenerator_x86_shared_h */