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
18namespace v8 {
19namespace internal {
20namespace compiler {
21
22class BasicBlock;
23class Schedule;
24
25
26class RawMachineAssembler : public GraphBuilder {
27 public:
28  class Label {
29   public:
30    Label() : block_(NULL), used_(false), bound_(false) {}
31    ~Label() { DCHECK(bound_ || !used_); }
32
33    BasicBlock* block() { return block_; }
34
35   private:
36    // Private constructor for exit label.
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);
49  virtual ~RawMachineAssembler() {}
50
51  Isolate* isolate() const { return zone()->isolate(); }
52  Zone* zone() const { return graph()->zone(); }
53  MachineOperatorBuilder* machine() { return &machine_; }
54  CommonOperatorBuilder* common() { return &common_; }
55  CallDescriptor* call_descriptor() const { return call_descriptor_; }
56  size_t parameter_count() const { return machine_sig_->parameter_count(); }
57  MachineSignature* machine_sig() const { return machine_sig_; }
58
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.
66  Node* PointerConstant(void* value) {
67    return IntPtrConstant(reinterpret_cast<intptr_t>(value));
68  }
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  }
74  Node* Int32Constant(int32_t value) {
75    return NewNode(common()->Int32Constant(value));
76  }
77  Node* Int64Constant(int64_t value) {
78    return NewNode(common()->Int64Constant(value));
79  }
80  Node* NumberConstant(double value) {
81    return NewNode(common()->NumberConstant(value));
82  }
83  Node* Float64Constant(double value) {
84    return NewNode(common()->Float64Constant(value));
85  }
86  Node* HeapConstant(Handle<Object> object) {
87    Unique<Object> val = Unique<Object>::CreateUninitialized(object);
88    return NewNode(common()->HeapConstant(val));
89  }
90
91  Node* Projection(int index, Node* a) {
92    return NewNode(common()->Projection(index), a);
93  }
94
95  // Memory Operations.
96  Node* Load(MachineType rep, Node* base) {
97    return Load(rep, base, Int32Constant(0));
98  }
99  Node* Load(MachineType rep, Node* base, Node* index) {
100    return NewNode(machine()->Load(rep), base, index);
101  }
102  void Store(MachineType rep, Node* base, Node* value) {
103    Store(rep, base, Int32Constant(0), value);
104  }
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.
110  Node* WordAnd(Node* a, Node* b) {
111    return NewNode(machine()->WordAnd(), a, b);
112  }
113  Node* WordOr(Node* a, Node* b) { return NewNode(machine()->WordOr(), a, b); }
114  Node* WordXor(Node* a, Node* b) {
115    return NewNode(machine()->WordXor(), a, b);
116  }
117  Node* WordShl(Node* a, Node* b) {
118    return NewNode(machine()->WordShl(), a, b);
119  }
120  Node* WordShr(Node* a, Node* b) {
121    return NewNode(machine()->WordShr(), a, b);
122  }
123  Node* WordSar(Node* a, Node* b) {
124    return NewNode(machine()->WordSar(), a, b);
125  }
126  Node* WordRor(Node* a, Node* b) {
127    return NewNode(machine()->WordRor(), a, b);
128  }
129  Node* WordEqual(Node* a, Node* b) {
130    return NewNode(machine()->WordEqual(), a, b);
131  }
132  Node* WordNotEqual(Node* a, Node* b) {
133    return WordBinaryNot(WordEqual(a, b));
134  }
135  Node* WordNot(Node* a) {
136    if (machine()->Is32()) {
137      return Word32Not(a);
138    } else {
139      return Word64Not(a);
140    }
141  }
142  Node* WordBinaryNot(Node* a) {
143    if (machine()->Is32()) {
144      return Word32BinaryNot(a);
145    } else {
146      return Word64BinaryNot(a);
147    }
148  }
149
150  Node* Word32And(Node* a, Node* b) {
151    return NewNode(machine()->Word32And(), a, b);
152  }
153  Node* Word32Or(Node* a, Node* b) {
154    return NewNode(machine()->Word32Or(), a, b);
155  }
156  Node* Word32Xor(Node* a, Node* b) {
157    return NewNode(machine()->Word32Xor(), a, b);
158  }
159  Node* Word32Shl(Node* a, Node* b) {
160    return NewNode(machine()->Word32Shl(), a, b);
161  }
162  Node* Word32Shr(Node* a, Node* b) {
163    return NewNode(machine()->Word32Shr(), a, b);
164  }
165  Node* Word32Sar(Node* a, Node* b) {
166    return NewNode(machine()->Word32Sar(), a, b);
167  }
168  Node* Word32Ror(Node* a, Node* b) {
169    return NewNode(machine()->Word32Ror(), a, b);
170  }
171  Node* Word32Equal(Node* a, Node* b) {
172    return NewNode(machine()->Word32Equal(), a, b);
173  }
174  Node* Word32NotEqual(Node* a, Node* b) {
175    return Word32BinaryNot(Word32Equal(a, b));
176  }
177  Node* Word32Not(Node* a) { return Word32Xor(a, Int32Constant(-1)); }
178  Node* Word32BinaryNot(Node* a) { return Word32Equal(a, Int32Constant(0)); }
179
180  Node* Word64And(Node* a, Node* b) {
181    return NewNode(machine()->Word64And(), a, b);
182  }
183  Node* Word64Or(Node* a, Node* b) {
184    return NewNode(machine()->Word64Or(), a, b);
185  }
186  Node* Word64Xor(Node* a, Node* b) {
187    return NewNode(machine()->Word64Xor(), a, b);
188  }
189  Node* Word64Shl(Node* a, Node* b) {
190    return NewNode(machine()->Word64Shl(), a, b);
191  }
192  Node* Word64Shr(Node* a, Node* b) {
193    return NewNode(machine()->Word64Shr(), a, b);
194  }
195  Node* Word64Sar(Node* a, Node* b) {
196    return NewNode(machine()->Word64Sar(), a, b);
197  }
198  Node* Word64Ror(Node* a, Node* b) {
199    return NewNode(machine()->Word64Ror(), a, b);
200  }
201  Node* Word64Equal(Node* a, Node* b) {
202    return NewNode(machine()->Word64Equal(), a, b);
203  }
204  Node* Word64NotEqual(Node* a, Node* b) {
205    return Word64BinaryNot(Word64Equal(a, b));
206  }
207  Node* Word64Not(Node* a) { return Word64Xor(a, Int64Constant(-1)); }
208  Node* Word64BinaryNot(Node* a) { return Word64Equal(a, Int64Constant(0)); }
209
210  Node* Int32Add(Node* a, Node* b) {
211    return NewNode(machine()->Int32Add(), a, b);
212  }
213  Node* Int32AddWithOverflow(Node* a, Node* b) {
214    return NewNode(machine()->Int32AddWithOverflow(), a, b);
215  }
216  Node* Int32Sub(Node* a, Node* b) {
217    return NewNode(machine()->Int32Sub(), a, b);
218  }
219  Node* Int32SubWithOverflow(Node* a, Node* b) {
220    return NewNode(machine()->Int32SubWithOverflow(), a, b);
221  }
222  Node* Int32Mul(Node* a, Node* b) {
223    return NewNode(machine()->Int32Mul(), a, b);
224  }
225  Node* Int32Div(Node* a, Node* b) {
226    return NewNode(machine()->Int32Div(), a, b);
227  }
228  Node* Int32UDiv(Node* a, Node* b) {
229    return NewNode(machine()->Int32UDiv(), a, b);
230  }
231  Node* Int32Mod(Node* a, Node* b) {
232    return NewNode(machine()->Int32Mod(), a, b);
233  }
234  Node* Int32UMod(Node* a, Node* b) {
235    return NewNode(machine()->Int32UMod(), a, b);
236  }
237  Node* Int32LessThan(Node* a, Node* b) {
238    return NewNode(machine()->Int32LessThan(), a, b);
239  }
240  Node* Int32LessThanOrEqual(Node* a, Node* b) {
241    return NewNode(machine()->Int32LessThanOrEqual(), a, b);
242  }
243  Node* Uint32LessThan(Node* a, Node* b) {
244    return NewNode(machine()->Uint32LessThan(), a, b);
245  }
246  Node* Uint32LessThanOrEqual(Node* a, Node* b) {
247    return NewNode(machine()->Uint32LessThanOrEqual(), a, b);
248  }
249  Node* Int32GreaterThan(Node* a, Node* b) { return Int32LessThan(b, a); }
250  Node* Int32GreaterThanOrEqual(Node* a, Node* b) {
251    return Int32LessThanOrEqual(b, a);
252  }
253  Node* Int32Neg(Node* a) { return Int32Sub(Int32Constant(0), a); }
254
255  Node* Int64Add(Node* a, Node* b) {
256    return NewNode(machine()->Int64Add(), a, b);
257  }
258  Node* Int64Sub(Node* a, Node* b) {
259    return NewNode(machine()->Int64Sub(), a, b);
260  }
261  Node* Int64Mul(Node* a, Node* b) {
262    return NewNode(machine()->Int64Mul(), a, b);
263  }
264  Node* Int64Div(Node* a, Node* b) {
265    return NewNode(machine()->Int64Div(), a, b);
266  }
267  Node* Int64UDiv(Node* a, Node* b) {
268    return NewNode(machine()->Int64UDiv(), a, b);
269  }
270  Node* Int64Mod(Node* a, Node* b) {
271    return NewNode(machine()->Int64Mod(), a, b);
272  }
273  Node* Int64UMod(Node* a, Node* b) {
274    return NewNode(machine()->Int64UMod(), a, b);
275  }
276  Node* Int64Neg(Node* a) { return Int64Sub(Int64Constant(0), a); }
277  Node* Int64LessThan(Node* a, Node* b) {
278    return NewNode(machine()->Int64LessThan(), a, b);
279  }
280  Node* Int64LessThanOrEqual(Node* a, Node* b) {
281    return NewNode(machine()->Int64LessThanOrEqual(), a, b);
282  }
283  Node* Int64GreaterThan(Node* a, Node* b) { return Int64LessThan(b, a); }
284  Node* Int64GreaterThanOrEqual(Node* a, Node* b) {
285    return Int64LessThanOrEqual(b, a);
286  }
287
288  // TODO(turbofan): What is this used for?
289  Node* ConvertIntPtrToInt32(Node* a) {
290    return kPointerSize == 8 ? NewNode(machine()->TruncateInt64ToInt32(), a)
291                             : a;
292  }
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
314  Node* Float64Add(Node* a, Node* b) {
315    return NewNode(machine()->Float64Add(), a, b);
316  }
317  Node* Float64Sub(Node* a, Node* b) {
318    return NewNode(machine()->Float64Sub(), a, b);
319  }
320  Node* Float64Mul(Node* a, Node* b) {
321    return NewNode(machine()->Float64Mul(), a, b);
322  }
323  Node* Float64Div(Node* a, Node* b) {
324    return NewNode(machine()->Float64Div(), a, b);
325  }
326  Node* Float64Mod(Node* a, Node* b) {
327    return NewNode(machine()->Float64Mod(), a, b);
328  }
329  Node* Float64Equal(Node* a, Node* b) {
330    return NewNode(machine()->Float64Equal(), a, b);
331  }
332  Node* Float64NotEqual(Node* a, Node* b) {
333    return WordBinaryNot(Float64Equal(a, b));
334  }
335  Node* Float64LessThan(Node* a, Node* b) {
336    return NewNode(machine()->Float64LessThan(), a, b);
337  }
338  Node* Float64LessThanOrEqual(Node* a, Node* b) {
339    return NewNode(machine()->Float64LessThanOrEqual(), a, b);
340  }
341  Node* Float64GreaterThan(Node* a, Node* b) { return Float64LessThan(b, a); }
342  Node* Float64GreaterThanOrEqual(Node* a, Node* b) {
343    return Float64LessThanOrEqual(b, a);
344  }
345
346  // Conversions.
347  Node* ChangeInt32ToFloat64(Node* a) {
348    return NewNode(machine()->ChangeInt32ToFloat64(), a);
349  }
350  Node* ChangeUint32ToFloat64(Node* a) {
351    return NewNode(machine()->ChangeUint32ToFloat64(), a);
352  }
353  Node* ChangeFloat64ToInt32(Node* a) {
354    return NewNode(machine()->ChangeFloat64ToInt32(), a);
355  }
356  Node* ChangeFloat64ToUint32(Node* a) {
357    return NewNode(machine()->ChangeFloat64ToUint32(), a);
358  }
359  Node* ChangeInt32ToInt64(Node* a) {
360    return NewNode(machine()->ChangeInt32ToInt64(), a);
361  }
362  Node* ChangeUint32ToUint64(Node* a) {
363    return NewNode(machine()->ChangeUint32ToUint64(), a);
364  }
365  Node* TruncateFloat64ToInt32(Node* a) {
366    return NewNode(machine()->TruncateFloat64ToInt32(), a);
367  }
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.
393  Node* Phi(MachineType type, Node* n1, Node* n2) {
394    return NewNode(common()->Phi(type, 2), n1, n2);
395  }
396  Node* Phi(MachineType type, Node* n1, Node* n2, Node* n3) {
397    return NewNode(common()->Phi(type, 3), n1, n2, n3);
398  }
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
410  bool ScheduleValid() { return schedule_ != NULL; }
411
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