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_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   friend class MoveResolverARM64;
21 
22  protected:
23   CodeGeneratorARM64(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm);
24 
25   NonAssertingLabel deoptLabel_;
26 
27   MoveOperand toMoveOperand(const LAllocation a) const;
28 
29   void bailoutIf(Assembler::Condition condition, LSnapshot* snapshot);
30   void bailoutFrom(Label* label, LSnapshot* snapshot);
31   void bailout(LSnapshot* snapshot);
32 
33   template <typename T1, typename T2>
bailoutCmpPtr(Assembler::Condition c,T1 lhs,T2 rhs,LSnapshot * snapshot)34   void bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs,
35                      LSnapshot* snapshot) {
36     masm.cmpPtr(lhs, rhs);
37     return bailoutIf(c, snapshot);
38   }
bailoutTestPtr(Assembler::Condition c,Register lhs,Register rhs,LSnapshot * snapshot)39   void bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs,
40                       LSnapshot* snapshot) {
41     masm.testPtr(lhs, rhs);
42     return bailoutIf(c, snapshot);
43   }
44   template <typename T1, typename T2>
bailoutCmp32(Assembler::Condition c,T1 lhs,T2 rhs,LSnapshot * snapshot)45   void bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs,
46                     LSnapshot* snapshot) {
47     masm.cmp32(lhs, rhs);
48     return bailoutIf(c, snapshot);
49   }
50   template <typename T1, typename T2>
bailoutTest32(Assembler::Condition c,T1 lhs,T2 rhs,LSnapshot * snapshot)51   void bailoutTest32(Assembler::Condition c, T1 lhs, T2 rhs,
52                      LSnapshot* snapshot) {
53     masm.test32(lhs, rhs);
54     return bailoutIf(c, snapshot);
55   }
bailoutIfFalseBool(Register reg,LSnapshot * snapshot)56   void bailoutIfFalseBool(Register reg, LSnapshot* snapshot) {
57     masm.test32(reg, Imm32(0xFF));
58     return bailoutIf(Assembler::Zero, snapshot);
59   }
60 
61   bool generateOutOfLineCode();
62 
63   // Emits a branch that directs control flow to the true block if |cond| is
64   // true, and the false block if |cond| is false.
65   void emitBranch(Assembler::Condition cond, MBasicBlock* ifTrue,
66                   MBasicBlock* ifFalse);
67 
testNullEmitBranch(Assembler::Condition cond,const ValueOperand & value,MBasicBlock * ifTrue,MBasicBlock * ifFalse)68   void testNullEmitBranch(Assembler::Condition cond, const ValueOperand& value,
69                           MBasicBlock* ifTrue, MBasicBlock* ifFalse) {
70     cond = masm.testNull(cond, value);
71     emitBranch(cond, ifTrue, ifFalse);
72   }
testUndefinedEmitBranch(Assembler::Condition cond,const ValueOperand & value,MBasicBlock * ifTrue,MBasicBlock * ifFalse)73   void testUndefinedEmitBranch(Assembler::Condition cond,
74                                const ValueOperand& value, MBasicBlock* ifTrue,
75                                MBasicBlock* ifFalse) {
76     cond = masm.testUndefined(cond, value);
77     emitBranch(cond, ifTrue, ifFalse);
78   }
testObjectEmitBranch(Assembler::Condition cond,const ValueOperand & value,MBasicBlock * ifTrue,MBasicBlock * ifFalse)79   void testObjectEmitBranch(Assembler::Condition cond,
80                             const ValueOperand& value, MBasicBlock* ifTrue,
81                             MBasicBlock* ifFalse) {
82     cond = masm.testObject(cond, value);
83     emitBranch(cond, ifTrue, ifFalse);
84   }
testZeroEmitBranch(Assembler::Condition cond,Register reg,MBasicBlock * ifTrue,MBasicBlock * ifFalse)85   void testZeroEmitBranch(Assembler::Condition cond, Register reg,
86                           MBasicBlock* ifTrue, MBasicBlock* ifFalse) {
87     MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
88     masm.cmpPtr(reg, ImmWord(0));
89     emitBranch(cond, ifTrue, ifFalse);
90   }
91 
92   void emitTableSwitchDispatch(MTableSwitch* mir, Register index,
93                                Register base);
94 
95   ValueOperand ToValue(LInstruction* ins, size_t pos);
96   ValueOperand ToTempValue(LInstruction* ins, size_t pos);
97 
98   void storeElementTyped(const LAllocation* value, MIRType valueType,
99                          MIRType elementType, Register elements,
100                          const LAllocation* index);
101 
102   void divICommon(MDiv* mir, Register lhs, Register rhs, Register output,
103                   LSnapshot* snapshot, Label& done);
104   void modICommon(MMod* mir, Register lhs, Register rhs, Register output,
105                   LSnapshot* snapshot, Label& done);
106 
107   void generateInvalidateEpilogue();
108 
109  public:
110   void visitOutOfLineBailout(OutOfLineBailout* ool);
111   void visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool);
112 };
113 
114 typedef CodeGeneratorARM64 CodeGeneratorSpecific;
115 
116 // An out-of-line bailout thunk.
117 class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorARM64> {
118  protected:  // Silence Clang warning.
119   LSnapshot* snapshot_;
120 
121  public:
OutOfLineBailout(LSnapshot * snapshot)122   explicit OutOfLineBailout(LSnapshot* snapshot) : snapshot_(snapshot) {}
123 
124   void accept(CodeGeneratorARM64* codegen) override;
125 
snapshot()126   LSnapshot* snapshot() const { return snapshot_; }
127 };
128 
129 }  // namespace jit
130 }  // namespace js
131 
132 #endif /* jit_arm64_CodeGenerator_arm64_h */
133