• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_
6 #define V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_
7 
8 #include "src/v8.h"
9 
10 #include "src/compiler/common-operator.h"
11 #include "src/compiler/graph-builder.h"
12 #include "src/compiler/linkage.h"
13 #include "src/compiler/machine-operator.h"
14 #include "src/compiler/node.h"
15 #include "src/compiler/operator.h"
16 
17 
18 namespace v8 {
19 namespace internal {
20 namespace compiler {
21 
22 class BasicBlock;
23 class Schedule;
24 
25 
26 class RawMachineAssembler : public GraphBuilder {
27  public:
28   class Label {
29    public:
Label()30     Label() : block_(NULL), used_(false), bound_(false) {}
~Label()31     ~Label() { DCHECK(bound_ || !used_); }
32 
block()33     BasicBlock* block() { return block_; }
34 
35    private:
36     // Private constructor for exit label.
Label(BasicBlock * block)37     explicit Label(BasicBlock* block)
38         : block_(block), used_(false), bound_(false) {}
39 
40     BasicBlock* block_;
41     bool used_;
42     bool bound_;
43     friend class RawMachineAssembler;
44     DISALLOW_COPY_AND_ASSIGN(Label);
45   };
46 
47   RawMachineAssembler(Graph* graph, MachineSignature* machine_sig,
48                       MachineType word = kMachPtr);
~RawMachineAssembler()49   virtual ~RawMachineAssembler() {}
50 
isolate()51   Isolate* isolate() const { return zone()->isolate(); }
zone()52   Zone* zone() const { return graph()->zone(); }
machine()53   MachineOperatorBuilder* machine() { return &machine_; }
common()54   CommonOperatorBuilder* common() { return &common_; }
call_descriptor()55   CallDescriptor* call_descriptor() const { return call_descriptor_; }
parameter_count()56   size_t parameter_count() const { return machine_sig_->parameter_count(); }
machine_sig()57   MachineSignature* machine_sig() const { return machine_sig_; }
58 
UndefinedConstant()59   Node* UndefinedConstant() {
60     Unique<Object> unique = Unique<Object>::CreateImmovable(
61         isolate()->factory()->undefined_value());
62     return NewNode(common()->HeapConstant(unique));
63   }
64 
65   // Constants.
PointerConstant(void * value)66   Node* PointerConstant(void* value) {
67     return IntPtrConstant(reinterpret_cast<intptr_t>(value));
68   }
IntPtrConstant(intptr_t value)69   Node* IntPtrConstant(intptr_t value) {
70     // TODO(dcarney): mark generated code as unserializable if value != 0.
71     return kPointerSize == 8 ? Int64Constant(value)
72                              : Int32Constant(static_cast<int>(value));
73   }
Int32Constant(int32_t value)74   Node* Int32Constant(int32_t value) {
75     return NewNode(common()->Int32Constant(value));
76   }
Int64Constant(int64_t value)77   Node* Int64Constant(int64_t value) {
78     return NewNode(common()->Int64Constant(value));
79   }
NumberConstant(double value)80   Node* NumberConstant(double value) {
81     return NewNode(common()->NumberConstant(value));
82   }
Float64Constant(double value)83   Node* Float64Constant(double value) {
84     return NewNode(common()->Float64Constant(value));
85   }
HeapConstant(Handle<Object> object)86   Node* HeapConstant(Handle<Object> object) {
87     Unique<Object> val = Unique<Object>::CreateUninitialized(object);
88     return NewNode(common()->HeapConstant(val));
89   }
90 
Projection(int index,Node * a)91   Node* Projection(int index, Node* a) {
92     return NewNode(common()->Projection(index), a);
93   }
94 
95   // Memory Operations.
Load(MachineType rep,Node * base)96   Node* Load(MachineType rep, Node* base) {
97     return Load(rep, base, Int32Constant(0));
98   }
Load(MachineType rep,Node * base,Node * index)99   Node* Load(MachineType rep, Node* base, Node* index) {
100     return NewNode(machine()->Load(rep), base, index);
101   }
Store(MachineType rep,Node * base,Node * value)102   void Store(MachineType rep, Node* base, Node* value) {
103     Store(rep, base, Int32Constant(0), value);
104   }
Store(MachineType rep,Node * base,Node * index,Node * value)105   void Store(MachineType rep, Node* base, Node* index, Node* value) {
106     NewNode(machine()->Store(StoreRepresentation(rep, kNoWriteBarrier)), base,
107             index, value);
108   }
109   // Arithmetic Operations.
WordAnd(Node * a,Node * b)110   Node* WordAnd(Node* a, Node* b) {
111     return NewNode(machine()->WordAnd(), a, b);
112   }
WordOr(Node * a,Node * b)113   Node* WordOr(Node* a, Node* b) { return NewNode(machine()->WordOr(), a, b); }
WordXor(Node * a,Node * b)114   Node* WordXor(Node* a, Node* b) {
115     return NewNode(machine()->WordXor(), a, b);
116   }
WordShl(Node * a,Node * b)117   Node* WordShl(Node* a, Node* b) {
118     return NewNode(machine()->WordShl(), a, b);
119   }
WordShr(Node * a,Node * b)120   Node* WordShr(Node* a, Node* b) {
121     return NewNode(machine()->WordShr(), a, b);
122   }
WordSar(Node * a,Node * b)123   Node* WordSar(Node* a, Node* b) {
124     return NewNode(machine()->WordSar(), a, b);
125   }
WordRor(Node * a,Node * b)126   Node* WordRor(Node* a, Node* b) {
127     return NewNode(machine()->WordRor(), a, b);
128   }
WordEqual(Node * a,Node * b)129   Node* WordEqual(Node* a, Node* b) {
130     return NewNode(machine()->WordEqual(), a, b);
131   }
WordNotEqual(Node * a,Node * b)132   Node* WordNotEqual(Node* a, Node* b) {
133     return WordBinaryNot(WordEqual(a, b));
134   }
WordNot(Node * a)135   Node* WordNot(Node* a) {
136     if (machine()->Is32()) {
137       return Word32Not(a);
138     } else {
139       return Word64Not(a);
140     }
141   }
WordBinaryNot(Node * a)142   Node* WordBinaryNot(Node* a) {
143     if (machine()->Is32()) {
144       return Word32BinaryNot(a);
145     } else {
146       return Word64BinaryNot(a);
147     }
148   }
149 
Word32And(Node * a,Node * b)150   Node* Word32And(Node* a, Node* b) {
151     return NewNode(machine()->Word32And(), a, b);
152   }
Word32Or(Node * a,Node * b)153   Node* Word32Or(Node* a, Node* b) {
154     return NewNode(machine()->Word32Or(), a, b);
155   }
Word32Xor(Node * a,Node * b)156   Node* Word32Xor(Node* a, Node* b) {
157     return NewNode(machine()->Word32Xor(), a, b);
158   }
Word32Shl(Node * a,Node * b)159   Node* Word32Shl(Node* a, Node* b) {
160     return NewNode(machine()->Word32Shl(), a, b);
161   }
Word32Shr(Node * a,Node * b)162   Node* Word32Shr(Node* a, Node* b) {
163     return NewNode(machine()->Word32Shr(), a, b);
164   }
Word32Sar(Node * a,Node * b)165   Node* Word32Sar(Node* a, Node* b) {
166     return NewNode(machine()->Word32Sar(), a, b);
167   }
Word32Ror(Node * a,Node * b)168   Node* Word32Ror(Node* a, Node* b) {
169     return NewNode(machine()->Word32Ror(), a, b);
170   }
Word32Equal(Node * a,Node * b)171   Node* Word32Equal(Node* a, Node* b) {
172     return NewNode(machine()->Word32Equal(), a, b);
173   }
Word32NotEqual(Node * a,Node * b)174   Node* Word32NotEqual(Node* a, Node* b) {
175     return Word32BinaryNot(Word32Equal(a, b));
176   }
Word32Not(Node * a)177   Node* Word32Not(Node* a) { return Word32Xor(a, Int32Constant(-1)); }
Word32BinaryNot(Node * a)178   Node* Word32BinaryNot(Node* a) { return Word32Equal(a, Int32Constant(0)); }
179 
Word64And(Node * a,Node * b)180   Node* Word64And(Node* a, Node* b) {
181     return NewNode(machine()->Word64And(), a, b);
182   }
Word64Or(Node * a,Node * b)183   Node* Word64Or(Node* a, Node* b) {
184     return NewNode(machine()->Word64Or(), a, b);
185   }
Word64Xor(Node * a,Node * b)186   Node* Word64Xor(Node* a, Node* b) {
187     return NewNode(machine()->Word64Xor(), a, b);
188   }
Word64Shl(Node * a,Node * b)189   Node* Word64Shl(Node* a, Node* b) {
190     return NewNode(machine()->Word64Shl(), a, b);
191   }
Word64Shr(Node * a,Node * b)192   Node* Word64Shr(Node* a, Node* b) {
193     return NewNode(machine()->Word64Shr(), a, b);
194   }
Word64Sar(Node * a,Node * b)195   Node* Word64Sar(Node* a, Node* b) {
196     return NewNode(machine()->Word64Sar(), a, b);
197   }
Word64Ror(Node * a,Node * b)198   Node* Word64Ror(Node* a, Node* b) {
199     return NewNode(machine()->Word64Ror(), a, b);
200   }
Word64Equal(Node * a,Node * b)201   Node* Word64Equal(Node* a, Node* b) {
202     return NewNode(machine()->Word64Equal(), a, b);
203   }
Word64NotEqual(Node * a,Node * b)204   Node* Word64NotEqual(Node* a, Node* b) {
205     return Word64BinaryNot(Word64Equal(a, b));
206   }
Word64Not(Node * a)207   Node* Word64Not(Node* a) { return Word64Xor(a, Int64Constant(-1)); }
Word64BinaryNot(Node * a)208   Node* Word64BinaryNot(Node* a) { return Word64Equal(a, Int64Constant(0)); }
209 
Int32Add(Node * a,Node * b)210   Node* Int32Add(Node* a, Node* b) {
211     return NewNode(machine()->Int32Add(), a, b);
212   }
Int32AddWithOverflow(Node * a,Node * b)213   Node* Int32AddWithOverflow(Node* a, Node* b) {
214     return NewNode(machine()->Int32AddWithOverflow(), a, b);
215   }
Int32Sub(Node * a,Node * b)216   Node* Int32Sub(Node* a, Node* b) {
217     return NewNode(machine()->Int32Sub(), a, b);
218   }
Int32SubWithOverflow(Node * a,Node * b)219   Node* Int32SubWithOverflow(Node* a, Node* b) {
220     return NewNode(machine()->Int32SubWithOverflow(), a, b);
221   }
Int32Mul(Node * a,Node * b)222   Node* Int32Mul(Node* a, Node* b) {
223     return NewNode(machine()->Int32Mul(), a, b);
224   }
Int32Div(Node * a,Node * b)225   Node* Int32Div(Node* a, Node* b) {
226     return NewNode(machine()->Int32Div(), a, b);
227   }
Int32UDiv(Node * a,Node * b)228   Node* Int32UDiv(Node* a, Node* b) {
229     return NewNode(machine()->Int32UDiv(), a, b);
230   }
Int32Mod(Node * a,Node * b)231   Node* Int32Mod(Node* a, Node* b) {
232     return NewNode(machine()->Int32Mod(), a, b);
233   }
Int32UMod(Node * a,Node * b)234   Node* Int32UMod(Node* a, Node* b) {
235     return NewNode(machine()->Int32UMod(), a, b);
236   }
Int32LessThan(Node * a,Node * b)237   Node* Int32LessThan(Node* a, Node* b) {
238     return NewNode(machine()->Int32LessThan(), a, b);
239   }
Int32LessThanOrEqual(Node * a,Node * b)240   Node* Int32LessThanOrEqual(Node* a, Node* b) {
241     return NewNode(machine()->Int32LessThanOrEqual(), a, b);
242   }
Uint32LessThan(Node * a,Node * b)243   Node* Uint32LessThan(Node* a, Node* b) {
244     return NewNode(machine()->Uint32LessThan(), a, b);
245   }
Uint32LessThanOrEqual(Node * a,Node * b)246   Node* Uint32LessThanOrEqual(Node* a, Node* b) {
247     return NewNode(machine()->Uint32LessThanOrEqual(), a, b);
248   }
Int32GreaterThan(Node * a,Node * b)249   Node* Int32GreaterThan(Node* a, Node* b) { return Int32LessThan(b, a); }
Int32GreaterThanOrEqual(Node * a,Node * b)250   Node* Int32GreaterThanOrEqual(Node* a, Node* b) {
251     return Int32LessThanOrEqual(b, a);
252   }
Int32Neg(Node * a)253   Node* Int32Neg(Node* a) { return Int32Sub(Int32Constant(0), a); }
254 
Int64Add(Node * a,Node * b)255   Node* Int64Add(Node* a, Node* b) {
256     return NewNode(machine()->Int64Add(), a, b);
257   }
Int64Sub(Node * a,Node * b)258   Node* Int64Sub(Node* a, Node* b) {
259     return NewNode(machine()->Int64Sub(), a, b);
260   }
Int64Mul(Node * a,Node * b)261   Node* Int64Mul(Node* a, Node* b) {
262     return NewNode(machine()->Int64Mul(), a, b);
263   }
Int64Div(Node * a,Node * b)264   Node* Int64Div(Node* a, Node* b) {
265     return NewNode(machine()->Int64Div(), a, b);
266   }
Int64UDiv(Node * a,Node * b)267   Node* Int64UDiv(Node* a, Node* b) {
268     return NewNode(machine()->Int64UDiv(), a, b);
269   }
Int64Mod(Node * a,Node * b)270   Node* Int64Mod(Node* a, Node* b) {
271     return NewNode(machine()->Int64Mod(), a, b);
272   }
Int64UMod(Node * a,Node * b)273   Node* Int64UMod(Node* a, Node* b) {
274     return NewNode(machine()->Int64UMod(), a, b);
275   }
Int64Neg(Node * a)276   Node* Int64Neg(Node* a) { return Int64Sub(Int64Constant(0), a); }
Int64LessThan(Node * a,Node * b)277   Node* Int64LessThan(Node* a, Node* b) {
278     return NewNode(machine()->Int64LessThan(), a, b);
279   }
Int64LessThanOrEqual(Node * a,Node * b)280   Node* Int64LessThanOrEqual(Node* a, Node* b) {
281     return NewNode(machine()->Int64LessThanOrEqual(), a, b);
282   }
Int64GreaterThan(Node * a,Node * b)283   Node* Int64GreaterThan(Node* a, Node* b) { return Int64LessThan(b, a); }
Int64GreaterThanOrEqual(Node * a,Node * b)284   Node* Int64GreaterThanOrEqual(Node* a, Node* b) {
285     return Int64LessThanOrEqual(b, a);
286   }
287 
288   // TODO(turbofan): What is this used for?
ConvertIntPtrToInt32(Node * a)289   Node* ConvertIntPtrToInt32(Node* a) {
290     return kPointerSize == 8 ? NewNode(machine()->TruncateInt64ToInt32(), a)
291                              : a;
292   }
ConvertInt32ToIntPtr(Node * a)293   Node* ConvertInt32ToIntPtr(Node* a) {
294     return kPointerSize == 8 ? NewNode(machine()->ChangeInt32ToInt64(), a) : a;
295   }
296 
297 #define INTPTR_BINOP(prefix, name)                     \
298   Node* IntPtr##name(Node* a, Node* b) {               \
299     return kPointerSize == 8 ? prefix##64##name(a, b)  \
300                              : prefix##32##name(a, b); \
301   }
302 
303   INTPTR_BINOP(Int, Add);
304   INTPTR_BINOP(Int, Sub);
305   INTPTR_BINOP(Int, LessThan);
306   INTPTR_BINOP(Int, LessThanOrEqual);
307   INTPTR_BINOP(Word, Equal);
308   INTPTR_BINOP(Word, NotEqual);
309   INTPTR_BINOP(Int, GreaterThanOrEqual);
310   INTPTR_BINOP(Int, GreaterThan);
311 
312 #undef INTPTR_BINOP
313 
Float64Add(Node * a,Node * b)314   Node* Float64Add(Node* a, Node* b) {
315     return NewNode(machine()->Float64Add(), a, b);
316   }
Float64Sub(Node * a,Node * b)317   Node* Float64Sub(Node* a, Node* b) {
318     return NewNode(machine()->Float64Sub(), a, b);
319   }
Float64Mul(Node * a,Node * b)320   Node* Float64Mul(Node* a, Node* b) {
321     return NewNode(machine()->Float64Mul(), a, b);
322   }
Float64Div(Node * a,Node * b)323   Node* Float64Div(Node* a, Node* b) {
324     return NewNode(machine()->Float64Div(), a, b);
325   }
Float64Mod(Node * a,Node * b)326   Node* Float64Mod(Node* a, Node* b) {
327     return NewNode(machine()->Float64Mod(), a, b);
328   }
Float64Equal(Node * a,Node * b)329   Node* Float64Equal(Node* a, Node* b) {
330     return NewNode(machine()->Float64Equal(), a, b);
331   }
Float64NotEqual(Node * a,Node * b)332   Node* Float64NotEqual(Node* a, Node* b) {
333     return WordBinaryNot(Float64Equal(a, b));
334   }
Float64LessThan(Node * a,Node * b)335   Node* Float64LessThan(Node* a, Node* b) {
336     return NewNode(machine()->Float64LessThan(), a, b);
337   }
Float64LessThanOrEqual(Node * a,Node * b)338   Node* Float64LessThanOrEqual(Node* a, Node* b) {
339     return NewNode(machine()->Float64LessThanOrEqual(), a, b);
340   }
Float64GreaterThan(Node * a,Node * b)341   Node* Float64GreaterThan(Node* a, Node* b) { return Float64LessThan(b, a); }
Float64GreaterThanOrEqual(Node * a,Node * b)342   Node* Float64GreaterThanOrEqual(Node* a, Node* b) {
343     return Float64LessThanOrEqual(b, a);
344   }
345 
346   // Conversions.
ChangeInt32ToFloat64(Node * a)347   Node* ChangeInt32ToFloat64(Node* a) {
348     return NewNode(machine()->ChangeInt32ToFloat64(), a);
349   }
ChangeUint32ToFloat64(Node * a)350   Node* ChangeUint32ToFloat64(Node* a) {
351     return NewNode(machine()->ChangeUint32ToFloat64(), a);
352   }
ChangeFloat64ToInt32(Node * a)353   Node* ChangeFloat64ToInt32(Node* a) {
354     return NewNode(machine()->ChangeFloat64ToInt32(), a);
355   }
ChangeFloat64ToUint32(Node * a)356   Node* ChangeFloat64ToUint32(Node* a) {
357     return NewNode(machine()->ChangeFloat64ToUint32(), a);
358   }
ChangeInt32ToInt64(Node * a)359   Node* ChangeInt32ToInt64(Node* a) {
360     return NewNode(machine()->ChangeInt32ToInt64(), a);
361   }
ChangeUint32ToUint64(Node * a)362   Node* ChangeUint32ToUint64(Node* a) {
363     return NewNode(machine()->ChangeUint32ToUint64(), a);
364   }
TruncateFloat64ToInt32(Node * a)365   Node* TruncateFloat64ToInt32(Node* a) {
366     return NewNode(machine()->TruncateFloat64ToInt32(), a);
367   }
TruncateInt64ToInt32(Node * a)368   Node* TruncateInt64ToInt32(Node* a) {
369     return NewNode(machine()->TruncateInt64ToInt32(), a);
370   }
371 
372   // Parameters.
373   Node* Parameter(size_t index);
374 
375   // Control flow.
376   Label* Exit();
377   void Goto(Label* label);
378   void Branch(Node* condition, Label* true_val, Label* false_val);
379   // Call through CallFunctionStub with lazy deopt and frame-state.
380   Node* CallFunctionStub0(Node* function, Node* receiver, Node* context,
381                           Node* frame_state, CallFunctionFlags flags);
382   // Call to a JS function with zero parameters.
383   Node* CallJS0(Node* function, Node* receiver, Node* context,
384                 Node* frame_state);
385   // Call to a runtime function with zero parameters.
386   Node* CallRuntime1(Runtime::FunctionId function, Node* arg0, Node* context,
387                      Node* frame_state);
388   void Return(Node* value);
389   void Bind(Label* label);
390   void Deoptimize(Node* state);
391 
392   // Variables.
Phi(MachineType type,Node * n1,Node * n2)393   Node* Phi(MachineType type, Node* n1, Node* n2) {
394     return NewNode(common()->Phi(type, 2), n1, n2);
395   }
Phi(MachineType type,Node * n1,Node * n2,Node * n3)396   Node* Phi(MachineType type, Node* n1, Node* n2, Node* n3) {
397     return NewNode(common()->Phi(type, 3), n1, n2, n3);
398   }
Phi(MachineType type,Node * n1,Node * n2,Node * n3,Node * n4)399   Node* Phi(MachineType type, Node* n1, Node* n2, Node* n3, Node* n4) {
400     return NewNode(common()->Phi(type, 4), n1, n2, n3, n4);
401   }
402 
403   // MachineAssembler is invalid after export.
404   Schedule* Export();
405 
406  protected:
407   virtual Node* MakeNode(const Operator* op, int input_count,
408                          Node** inputs) FINAL;
409 
ScheduleValid()410   bool ScheduleValid() { return schedule_ != NULL; }
411 
schedule()412   Schedule* schedule() {
413     DCHECK(ScheduleValid());
414     return schedule_;
415   }
416 
417  private:
418   BasicBlock* Use(Label* label);
419   BasicBlock* EnsureBlock(Label* label);
420   BasicBlock* CurrentBlock();
421 
422   Schedule* schedule_;
423   MachineOperatorBuilder machine_;
424   CommonOperatorBuilder common_;
425   MachineSignature* machine_sig_;
426   CallDescriptor* call_descriptor_;
427   Node** parameters_;
428   Label exit_label_;
429   BasicBlock* current_block_;
430 
431   DISALLOW_COPY_AND_ASSIGN(RawMachineAssembler);
432 };
433 
434 }  // namespace compiler
435 }  // namespace internal
436 }  // namespace v8
437 
438 #endif  // V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_
439