|
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_shared_Lowering_shared_h |
|
8 #define jit_shared_Lowering_shared_h |
|
9 |
|
10 // This file declares the structures that are used for attaching LIR to a |
|
11 // MIRGraph. |
|
12 |
|
13 #include "jit/LIR.h" |
|
14 |
|
15 namespace js { |
|
16 namespace jit { |
|
17 |
|
18 class MBasicBlock; |
|
19 class MTableSwitch; |
|
20 class MIRGenerator; |
|
21 class MIRGraph; |
|
22 class MDefinition; |
|
23 class MInstruction; |
|
24 class LOsiPoint; |
|
25 |
|
26 class LIRGeneratorShared : public MInstructionVisitorWithDefaults |
|
27 { |
|
28 protected: |
|
29 MIRGenerator *gen; |
|
30 MIRGraph &graph; |
|
31 LIRGraph &lirGraph_; |
|
32 LBlock *current; |
|
33 MResumePoint *lastResumePoint_; |
|
34 LRecoverInfo *cachedRecoverInfo_; |
|
35 LOsiPoint *osiPoint_; |
|
36 |
|
37 public: |
|
38 LIRGeneratorShared(MIRGenerator *gen, MIRGraph &graph, LIRGraph &lirGraph) |
|
39 : gen(gen), |
|
40 graph(graph), |
|
41 lirGraph_(lirGraph), |
|
42 lastResumePoint_(nullptr), |
|
43 cachedRecoverInfo_(nullptr), |
|
44 osiPoint_(nullptr) |
|
45 { } |
|
46 |
|
47 MIRGenerator *mir() { |
|
48 return gen; |
|
49 } |
|
50 |
|
51 protected: |
|
52 // A backend can decide that an instruction should be emitted at its uses, |
|
53 // rather than at its definition. To communicate this, set the |
|
54 // instruction's virtual register set to 0. When using the instruction, |
|
55 // its virtual register is temporarily reassigned. To know to clear it |
|
56 // after constructing the use information, the worklist bit is temporarily |
|
57 // unset. |
|
58 // |
|
59 // The backend can use the worklist bit to determine whether or not a |
|
60 // definition should be created. |
|
61 inline bool emitAtUses(MInstruction *mir); |
|
62 |
|
63 // The lowest-level calls to use, those that do not wrap another call to |
|
64 // use(), must prefix grabbing virtual register IDs by these calls. |
|
65 inline bool ensureDefined(MDefinition *mir); |
|
66 |
|
67 // These all create a use of a virtual register, with an optional |
|
68 // allocation policy. |
|
69 inline LUse use(MDefinition *mir, LUse policy); |
|
70 inline LUse use(MDefinition *mir); |
|
71 inline LUse useAtStart(MDefinition *mir); |
|
72 inline LUse useRegister(MDefinition *mir); |
|
73 inline LUse useRegisterAtStart(MDefinition *mir); |
|
74 inline LUse useFixed(MDefinition *mir, Register reg); |
|
75 inline LUse useFixed(MDefinition *mir, FloatRegister reg); |
|
76 inline LUse useFixed(MDefinition *mir, AnyRegister reg); |
|
77 inline LUse useFixedAtStart(MDefinition *mir, Register reg); |
|
78 inline LAllocation useOrConstant(MDefinition *mir); |
|
79 // "Any" is architecture dependent, and will include registers and stack slots on X86, |
|
80 // and only registers on ARM. |
|
81 inline LAllocation useAny(MDefinition *mir); |
|
82 inline LAllocation useAnyOrConstant(MDefinition *mir); |
|
83 // "Storable" is architecture dependend, and will include registers and constants on X86 |
|
84 // and only registers on ARM. |
|
85 // this is a generic "things we can expect to write into memory in 1 instruction" |
|
86 inline LAllocation useStorable(MDefinition *mir); |
|
87 inline LAllocation useStorableAtStart(MDefinition *mir); |
|
88 inline LAllocation useKeepaliveOrConstant(MDefinition *mir); |
|
89 inline LAllocation useRegisterOrConstant(MDefinition *mir); |
|
90 inline LAllocation useRegisterOrConstantAtStart(MDefinition *mir); |
|
91 inline LAllocation useRegisterOrNonNegativeConstantAtStart(MDefinition *mir); |
|
92 inline LAllocation useRegisterOrNonDoubleConstant(MDefinition *mir); |
|
93 |
|
94 #ifdef JS_NUNBOX32 |
|
95 inline LUse useType(MDefinition *mir, LUse::Policy policy); |
|
96 inline LUse usePayload(MDefinition *mir, LUse::Policy policy); |
|
97 inline LUse usePayloadAtStart(MDefinition *mir, LUse::Policy policy); |
|
98 inline LUse usePayloadInRegisterAtStart(MDefinition *mir); |
|
99 |
|
100 // Adds a box input to an instruction, setting operand |n| to the type and |
|
101 // |n+1| to the payload. Does not modify the operands, instead expecting a |
|
102 // policy to already be set. |
|
103 inline bool fillBoxUses(LInstruction *lir, size_t n, MDefinition *mir); |
|
104 #endif |
|
105 |
|
106 // These create temporary register requests. |
|
107 inline LDefinition temp(LDefinition::Type type = LDefinition::GENERAL, |
|
108 LDefinition::Policy policy = LDefinition::DEFAULT); |
|
109 inline LDefinition tempFloat32(); |
|
110 inline LDefinition tempDouble(); |
|
111 inline LDefinition tempCopy(MDefinition *input, uint32_t reusedInput); |
|
112 |
|
113 // Note that the fixed register has a GENERAL type. |
|
114 inline LDefinition tempFixed(Register reg); |
|
115 |
|
116 template <size_t Ops, size_t Temps> |
|
117 inline bool defineFixed(LInstructionHelper<1, Ops, Temps> *lir, MDefinition *mir, |
|
118 const LAllocation &output); |
|
119 |
|
120 template <size_t Ops, size_t Temps> |
|
121 inline bool defineBox(LInstructionHelper<BOX_PIECES, Ops, Temps> *lir, MDefinition *mir, |
|
122 LDefinition::Policy policy = LDefinition::DEFAULT); |
|
123 |
|
124 inline bool defineReturn(LInstruction *lir, MDefinition *mir); |
|
125 |
|
126 template <size_t Ops, size_t Temps> |
|
127 inline bool define(LInstructionHelper<1, Ops, Temps> *lir, MDefinition *mir, |
|
128 const LDefinition &def); |
|
129 |
|
130 template <size_t Ops, size_t Temps> |
|
131 inline bool define(LInstructionHelper<1, Ops, Temps> *lir, MDefinition *mir, |
|
132 LDefinition::Policy policy = LDefinition::DEFAULT); |
|
133 |
|
134 template <size_t Ops, size_t Temps> |
|
135 inline bool defineReuseInput(LInstructionHelper<1, Ops, Temps> *lir, MDefinition *mir, uint32_t operand); |
|
136 |
|
137 // Rather than defining a new virtual register, sets |ins| to have the same |
|
138 // virtual register as |as|. |
|
139 inline bool redefine(MDefinition *ins, MDefinition *as); |
|
140 |
|
141 // Defines an IR's output as the same as another IR. This is similar to |
|
142 // redefine(), but used when creating new LIR. |
|
143 inline bool defineAs(LInstruction *outLir, MDefinition *outMir, MDefinition *inMir); |
|
144 |
|
145 TempAllocator &alloc() const { |
|
146 return graph.alloc(); |
|
147 } |
|
148 |
|
149 uint32_t getVirtualRegister() { |
|
150 return lirGraph_.getVirtualRegister(); |
|
151 } |
|
152 |
|
153 template <typename T> void annotate(T *ins); |
|
154 template <typename T> bool add(T *ins, MInstruction *mir = nullptr); |
|
155 |
|
156 void lowerTypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock *block, size_t lirIndex); |
|
157 bool defineTypedPhi(MPhi *phi, size_t lirIndex); |
|
158 |
|
159 LOsiPoint *popOsiPoint() { |
|
160 LOsiPoint *tmp = osiPoint_; |
|
161 osiPoint_ = nullptr; |
|
162 return tmp; |
|
163 } |
|
164 |
|
165 LRecoverInfo *getRecoverInfo(MResumePoint *rp); |
|
166 LSnapshot *buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKind kind); |
|
167 bool assignPostSnapshot(MInstruction *mir, LInstruction *ins); |
|
168 |
|
169 // Marks this instruction as fallible, meaning that before it performs |
|
170 // effects (if any), it may check pre-conditions and bailout if they do not |
|
171 // hold. This function informs the register allocator that it will need to |
|
172 // capture appropriate state. |
|
173 bool assignSnapshot(LInstruction *ins, BailoutKind kind = Bailout_Normal); |
|
174 |
|
175 // Marks this instruction as needing to call into either the VM or GC. This |
|
176 // function may build a snapshot that captures the result of its own |
|
177 // instruction, and as such, should generally be called after define*(). |
|
178 bool assignSafepoint(LInstruction *ins, MInstruction *mir); |
|
179 |
|
180 public: |
|
181 bool visitConstant(MConstant *ins); |
|
182 |
|
183 // Whether to generate typed reads for element accesses with hole checks. |
|
184 static bool allowTypedElementHoleCheck() { |
|
185 return false; |
|
186 } |
|
187 |
|
188 // Whether to generate typed array accesses on statically known objects. |
|
189 static bool allowStaticTypedArrayAccesses() { |
|
190 return false; |
|
191 } |
|
192 |
|
193 // Whether we can emit Float32 specific optimizations. |
|
194 static bool allowFloat32Optimizations() { |
|
195 return false; |
|
196 } |
|
197 |
|
198 // Whether we can inline ForkJoinGetSlice. |
|
199 static bool allowInlineForkJoinGetSlice() { |
|
200 return false; |
|
201 } |
|
202 }; |
|
203 |
|
204 } // namespace jit |
|
205 } // namespace js |
|
206 |
|
207 #endif /* jit_shared_Lowering_shared_h */ |