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/assembler.h"
9 #include "src/compiler/common-operator.h"
10 #include "src/compiler/graph.h"
11 #include "src/compiler/linkage.h"
12 #include "src/compiler/machine-operator.h"
13 #include "src/compiler/node.h"
14 #include "src/compiler/operator.h"
15 #include "src/factory.h"
16 
17 namespace v8 {
18 namespace internal {
19 namespace compiler {
20 
21 class BasicBlock;
22 class RawMachineLabel;
23 class Schedule;
24 
25 
26 // The RawMachineAssembler produces a low-level IR graph. All nodes are wired
27 // into a graph and also placed into a schedule immediately, hence subsequent
28 // code generation can happen without the need for scheduling.
29 //
30 // In order to create a schedule on-the-fly, the assembler keeps track of basic
31 // blocks by having one current basic block being populated and by referencing
32 // other basic blocks through the use of labels.
33 //
34 // Also note that the generated graph is only valid together with the generated
35 // schedule, using one without the other is invalid as the graph is inherently
36 // non-schedulable due to missing control and effect dependencies.
37 class RawMachineAssembler {
38  public:
39   RawMachineAssembler(
40       Isolate* isolate, Graph* graph, CallDescriptor* call_descriptor,
41       MachineRepresentation word = MachineType::PointerRepresentation(),
42       MachineOperatorBuilder::Flags flags =
43           MachineOperatorBuilder::Flag::kNoFlags);
~RawMachineAssembler()44   ~RawMachineAssembler() {}
45 
isolate()46   Isolate* isolate() const { return isolate_; }
graph()47   Graph* graph() const { return graph_; }
zone()48   Zone* zone() const { return graph()->zone(); }
machine()49   MachineOperatorBuilder* machine() { return &machine_; }
common()50   CommonOperatorBuilder* common() { return &common_; }
call_descriptor()51   CallDescriptor* call_descriptor() const { return call_descriptor_; }
52 
53   // Finalizes the schedule and exports it to be used for code generation. Note
54   // that this RawMachineAssembler becomes invalid after export.
55   Schedule* Export();
56 
57   // ===========================================================================
58   // The following utility methods create new nodes with specific operators and
59   // place them into the current basic block. They don't perform control flow,
60   // hence will not switch the current basic block.
61 
NullConstant()62   Node* NullConstant() {
63     return HeapConstant(isolate()->factory()->null_value());
64   }
65 
UndefinedConstant()66   Node* UndefinedConstant() {
67     return HeapConstant(isolate()->factory()->undefined_value());
68   }
69 
70   // Constants.
PointerConstant(void * value)71   Node* PointerConstant(void* value) {
72     return IntPtrConstant(reinterpret_cast<intptr_t>(value));
73   }
IntPtrConstant(intptr_t value)74   Node* IntPtrConstant(intptr_t value) {
75     // TODO(dcarney): mark generated code as unserializable if value != 0.
76     return kPointerSize == 8 ? Int64Constant(value)
77                              : Int32Constant(static_cast<int>(value));
78   }
Int32Constant(int32_t value)79   Node* Int32Constant(int32_t value) {
80     return AddNode(common()->Int32Constant(value));
81   }
Int64Constant(int64_t value)82   Node* Int64Constant(int64_t value) {
83     return AddNode(common()->Int64Constant(value));
84   }
NumberConstant(double value)85   Node* NumberConstant(double value) {
86     return AddNode(common()->NumberConstant(value));
87   }
Float32Constant(float value)88   Node* Float32Constant(float value) {
89     return AddNode(common()->Float32Constant(value));
90   }
Float64Constant(double value)91   Node* Float64Constant(double value) {
92     return AddNode(common()->Float64Constant(value));
93   }
HeapConstant(Handle<HeapObject> object)94   Node* HeapConstant(Handle<HeapObject> object) {
95     return AddNode(common()->HeapConstant(object));
96   }
BooleanConstant(bool value)97   Node* BooleanConstant(bool value) {
98     Handle<Object> object = isolate()->factory()->ToBoolean(value);
99     return HeapConstant(Handle<HeapObject>::cast(object));
100   }
ExternalConstant(ExternalReference address)101   Node* ExternalConstant(ExternalReference address) {
102     return AddNode(common()->ExternalConstant(address));
103   }
104 
Projection(int index,Node * a)105   Node* Projection(int index, Node* a) {
106     return AddNode(common()->Projection(index), a);
107   }
108 
109   // Memory Operations.
Load(MachineType rep,Node * base)110   Node* Load(MachineType rep, Node* base) {
111     return Load(rep, base, IntPtrConstant(0));
112   }
Load(MachineType rep,Node * base,Node * index)113   Node* Load(MachineType rep, Node* base, Node* index) {
114     return AddNode(machine()->Load(rep), base, index);
115   }
Store(MachineRepresentation rep,Node * base,Node * value,WriteBarrierKind write_barrier)116   Node* Store(MachineRepresentation rep, Node* base, Node* value,
117               WriteBarrierKind write_barrier) {
118     return Store(rep, base, IntPtrConstant(0), value, write_barrier);
119   }
Store(MachineRepresentation rep,Node * base,Node * index,Node * value,WriteBarrierKind write_barrier)120   Node* Store(MachineRepresentation rep, Node* base, Node* index, Node* value,
121               WriteBarrierKind write_barrier) {
122     return AddNode(machine()->Store(StoreRepresentation(rep, write_barrier)),
123                    base, index, value);
124   }
125 
126   // Arithmetic Operations.
WordAnd(Node * a,Node * b)127   Node* WordAnd(Node* a, Node* b) {
128     return AddNode(machine()->WordAnd(), a, b);
129   }
WordOr(Node * a,Node * b)130   Node* WordOr(Node* a, Node* b) { return AddNode(machine()->WordOr(), a, b); }
WordXor(Node * a,Node * b)131   Node* WordXor(Node* a, Node* b) {
132     return AddNode(machine()->WordXor(), a, b);
133   }
WordShl(Node * a,Node * b)134   Node* WordShl(Node* a, Node* b) {
135     return AddNode(machine()->WordShl(), a, b);
136   }
WordShr(Node * a,Node * b)137   Node* WordShr(Node* a, Node* b) {
138     return AddNode(machine()->WordShr(), a, b);
139   }
WordSar(Node * a,Node * b)140   Node* WordSar(Node* a, Node* b) {
141     return AddNode(machine()->WordSar(), a, b);
142   }
WordRor(Node * a,Node * b)143   Node* WordRor(Node* a, Node* b) {
144     return AddNode(machine()->WordRor(), a, b);
145   }
WordEqual(Node * a,Node * b)146   Node* WordEqual(Node* a, Node* b) {
147     return AddNode(machine()->WordEqual(), a, b);
148   }
WordNotEqual(Node * a,Node * b)149   Node* WordNotEqual(Node* a, Node* b) {
150     return WordBinaryNot(WordEqual(a, b));
151   }
WordNot(Node * a)152   Node* WordNot(Node* a) {
153     if (machine()->Is32()) {
154       return Word32Not(a);
155     } else {
156       return Word64Not(a);
157     }
158   }
WordBinaryNot(Node * a)159   Node* WordBinaryNot(Node* a) {
160     if (machine()->Is32()) {
161       return Word32BinaryNot(a);
162     } else {
163       return Word64BinaryNot(a);
164     }
165   }
166 
Word32And(Node * a,Node * b)167   Node* Word32And(Node* a, Node* b) {
168     return AddNode(machine()->Word32And(), a, b);
169   }
Word32Or(Node * a,Node * b)170   Node* Word32Or(Node* a, Node* b) {
171     return AddNode(machine()->Word32Or(), a, b);
172   }
Word32Xor(Node * a,Node * b)173   Node* Word32Xor(Node* a, Node* b) {
174     return AddNode(machine()->Word32Xor(), a, b);
175   }
Word32Shl(Node * a,Node * b)176   Node* Word32Shl(Node* a, Node* b) {
177     return AddNode(machine()->Word32Shl(), a, b);
178   }
Word32Shr(Node * a,Node * b)179   Node* Word32Shr(Node* a, Node* b) {
180     return AddNode(machine()->Word32Shr(), a, b);
181   }
Word32Sar(Node * a,Node * b)182   Node* Word32Sar(Node* a, Node* b) {
183     return AddNode(machine()->Word32Sar(), a, b);
184   }
Word32Ror(Node * a,Node * b)185   Node* Word32Ror(Node* a, Node* b) {
186     return AddNode(machine()->Word32Ror(), a, b);
187   }
Word32Clz(Node * a)188   Node* Word32Clz(Node* a) { return AddNode(machine()->Word32Clz(), a); }
Word32Equal(Node * a,Node * b)189   Node* Word32Equal(Node* a, Node* b) {
190     return AddNode(machine()->Word32Equal(), a, b);
191   }
Word32NotEqual(Node * a,Node * b)192   Node* Word32NotEqual(Node* a, Node* b) {
193     return Word32BinaryNot(Word32Equal(a, b));
194   }
Word32Not(Node * a)195   Node* Word32Not(Node* a) { return Word32Xor(a, Int32Constant(-1)); }
Word32BinaryNot(Node * a)196   Node* Word32BinaryNot(Node* a) { return Word32Equal(a, Int32Constant(0)); }
197 
Word64And(Node * a,Node * b)198   Node* Word64And(Node* a, Node* b) {
199     return AddNode(machine()->Word64And(), a, b);
200   }
Word64Or(Node * a,Node * b)201   Node* Word64Or(Node* a, Node* b) {
202     return AddNode(machine()->Word64Or(), a, b);
203   }
Word64Xor(Node * a,Node * b)204   Node* Word64Xor(Node* a, Node* b) {
205     return AddNode(machine()->Word64Xor(), a, b);
206   }
Word64Shl(Node * a,Node * b)207   Node* Word64Shl(Node* a, Node* b) {
208     return AddNode(machine()->Word64Shl(), a, b);
209   }
Word64Shr(Node * a,Node * b)210   Node* Word64Shr(Node* a, Node* b) {
211     return AddNode(machine()->Word64Shr(), a, b);
212   }
Word64Sar(Node * a,Node * b)213   Node* Word64Sar(Node* a, Node* b) {
214     return AddNode(machine()->Word64Sar(), a, b);
215   }
Word64Ror(Node * a,Node * b)216   Node* Word64Ror(Node* a, Node* b) {
217     return AddNode(machine()->Word64Ror(), a, b);
218   }
Word64Clz(Node * a)219   Node* Word64Clz(Node* a) { return AddNode(machine()->Word64Clz(), a); }
Word64Equal(Node * a,Node * b)220   Node* Word64Equal(Node* a, Node* b) {
221     return AddNode(machine()->Word64Equal(), a, b);
222   }
Word64NotEqual(Node * a,Node * b)223   Node* Word64NotEqual(Node* a, Node* b) {
224     return Word64BinaryNot(Word64Equal(a, b));
225   }
Word64Not(Node * a)226   Node* Word64Not(Node* a) { return Word64Xor(a, Int64Constant(-1)); }
Word64BinaryNot(Node * a)227   Node* Word64BinaryNot(Node* a) { return Word64Equal(a, Int64Constant(0)); }
228 
Int32Add(Node * a,Node * b)229   Node* Int32Add(Node* a, Node* b) {
230     return AddNode(machine()->Int32Add(), a, b);
231   }
Int32AddWithOverflow(Node * a,Node * b)232   Node* Int32AddWithOverflow(Node* a, Node* b) {
233     return AddNode(machine()->Int32AddWithOverflow(), a, b);
234   }
Int32Sub(Node * a,Node * b)235   Node* Int32Sub(Node* a, Node* b) {
236     return AddNode(machine()->Int32Sub(), a, b);
237   }
Int32SubWithOverflow(Node * a,Node * b)238   Node* Int32SubWithOverflow(Node* a, Node* b) {
239     return AddNode(machine()->Int32SubWithOverflow(), a, b);
240   }
Int32Mul(Node * a,Node * b)241   Node* Int32Mul(Node* a, Node* b) {
242     return AddNode(machine()->Int32Mul(), a, b);
243   }
Int32MulHigh(Node * a,Node * b)244   Node* Int32MulHigh(Node* a, Node* b) {
245     return AddNode(machine()->Int32MulHigh(), a, b);
246   }
Int32Div(Node * a,Node * b)247   Node* Int32Div(Node* a, Node* b) {
248     return AddNode(machine()->Int32Div(), a, b);
249   }
Int32Mod(Node * a,Node * b)250   Node* Int32Mod(Node* a, Node* b) {
251     return AddNode(machine()->Int32Mod(), a, b);
252   }
Int32LessThan(Node * a,Node * b)253   Node* Int32LessThan(Node* a, Node* b) {
254     return AddNode(machine()->Int32LessThan(), a, b);
255   }
Int32LessThanOrEqual(Node * a,Node * b)256   Node* Int32LessThanOrEqual(Node* a, Node* b) {
257     return AddNode(machine()->Int32LessThanOrEqual(), a, b);
258   }
Uint32Div(Node * a,Node * b)259   Node* Uint32Div(Node* a, Node* b) {
260     return AddNode(machine()->Uint32Div(), a, b);
261   }
Uint32LessThan(Node * a,Node * b)262   Node* Uint32LessThan(Node* a, Node* b) {
263     return AddNode(machine()->Uint32LessThan(), a, b);
264   }
Uint32LessThanOrEqual(Node * a,Node * b)265   Node* Uint32LessThanOrEqual(Node* a, Node* b) {
266     return AddNode(machine()->Uint32LessThanOrEqual(), a, b);
267   }
Uint32Mod(Node * a,Node * b)268   Node* Uint32Mod(Node* a, Node* b) {
269     return AddNode(machine()->Uint32Mod(), a, b);
270   }
Uint32MulHigh(Node * a,Node * b)271   Node* Uint32MulHigh(Node* a, Node* b) {
272     return AddNode(machine()->Uint32MulHigh(), a, b);
273   }
Int32GreaterThan(Node * a,Node * b)274   Node* Int32GreaterThan(Node* a, Node* b) { return Int32LessThan(b, a); }
Int32GreaterThanOrEqual(Node * a,Node * b)275   Node* Int32GreaterThanOrEqual(Node* a, Node* b) {
276     return Int32LessThanOrEqual(b, a);
277   }
Int32Neg(Node * a)278   Node* Int32Neg(Node* a) { return Int32Sub(Int32Constant(0), a); }
279 
Int64Add(Node * a,Node * b)280   Node* Int64Add(Node* a, Node* b) {
281     return AddNode(machine()->Int64Add(), a, b);
282   }
Int64AddWithOverflow(Node * a,Node * b)283   Node* Int64AddWithOverflow(Node* a, Node* b) {
284     return AddNode(machine()->Int64AddWithOverflow(), a, b);
285   }
Int64Sub(Node * a,Node * b)286   Node* Int64Sub(Node* a, Node* b) {
287     return AddNode(machine()->Int64Sub(), a, b);
288   }
Int64SubWithOverflow(Node * a,Node * b)289   Node* Int64SubWithOverflow(Node* a, Node* b) {
290     return AddNode(machine()->Int64SubWithOverflow(), a, b);
291   }
Int64Mul(Node * a,Node * b)292   Node* Int64Mul(Node* a, Node* b) {
293     return AddNode(machine()->Int64Mul(), a, b);
294   }
Int64Div(Node * a,Node * b)295   Node* Int64Div(Node* a, Node* b) {
296     return AddNode(machine()->Int64Div(), a, b);
297   }
Int64Mod(Node * a,Node * b)298   Node* Int64Mod(Node* a, Node* b) {
299     return AddNode(machine()->Int64Mod(), a, b);
300   }
Int64Neg(Node * a)301   Node* Int64Neg(Node* a) { return Int64Sub(Int64Constant(0), a); }
Int64LessThan(Node * a,Node * b)302   Node* Int64LessThan(Node* a, Node* b) {
303     return AddNode(machine()->Int64LessThan(), a, b);
304   }
Int64LessThanOrEqual(Node * a,Node * b)305   Node* Int64LessThanOrEqual(Node* a, Node* b) {
306     return AddNode(machine()->Int64LessThanOrEqual(), a, b);
307   }
Uint64LessThan(Node * a,Node * b)308   Node* Uint64LessThan(Node* a, Node* b) {
309     return AddNode(machine()->Uint64LessThan(), a, b);
310   }
Uint64LessThanOrEqual(Node * a,Node * b)311   Node* Uint64LessThanOrEqual(Node* a, Node* b) {
312     return AddNode(machine()->Uint64LessThanOrEqual(), a, b);
313   }
Int64GreaterThan(Node * a,Node * b)314   Node* Int64GreaterThan(Node* a, Node* b) { return Int64LessThan(b, a); }
Int64GreaterThanOrEqual(Node * a,Node * b)315   Node* Int64GreaterThanOrEqual(Node* a, Node* b) {
316     return Int64LessThanOrEqual(b, a);
317   }
Uint64Div(Node * a,Node * b)318   Node* Uint64Div(Node* a, Node* b) {
319     return AddNode(machine()->Uint64Div(), a, b);
320   }
Uint64Mod(Node * a,Node * b)321   Node* Uint64Mod(Node* a, Node* b) {
322     return AddNode(machine()->Uint64Mod(), a, b);
323   }
324 
325 #define INTPTR_BINOP(prefix, name)                     \
326   Node* IntPtr##name(Node* a, Node* b) {               \
327     return kPointerSize == 8 ? prefix##64##name(a, b)  \
328                              : prefix##32##name(a, b); \
329   }
330 
331   INTPTR_BINOP(Int, Add);
332   INTPTR_BINOP(Int, Sub);
333   INTPTR_BINOP(Int, LessThan);
334   INTPTR_BINOP(Int, LessThanOrEqual);
335   INTPTR_BINOP(Word, Equal);
336   INTPTR_BINOP(Word, NotEqual);
337   INTPTR_BINOP(Int, GreaterThanOrEqual);
338   INTPTR_BINOP(Int, GreaterThan);
339 
340 #undef INTPTR_BINOP
341 
Float32Add(Node * a,Node * b)342   Node* Float32Add(Node* a, Node* b) {
343     return AddNode(machine()->Float32Add(), a, b);
344   }
Float32Sub(Node * a,Node * b)345   Node* Float32Sub(Node* a, Node* b) {
346     return AddNode(machine()->Float32Sub(), a, b);
347   }
Float32Mul(Node * a,Node * b)348   Node* Float32Mul(Node* a, Node* b) {
349     return AddNode(machine()->Float32Mul(), a, b);
350   }
Float32Div(Node * a,Node * b)351   Node* Float32Div(Node* a, Node* b) {
352     return AddNode(machine()->Float32Div(), a, b);
353   }
Float32Max(Node * a,Node * b)354   Node* Float32Max(Node* a, Node* b) {
355     return AddNode(machine()->Float32Max().op(), a, b);
356   }
Float32Min(Node * a,Node * b)357   Node* Float32Min(Node* a, Node* b) {
358     return AddNode(machine()->Float32Min().op(), a, b);
359   }
Float32Abs(Node * a)360   Node* Float32Abs(Node* a) { return AddNode(machine()->Float32Abs(), a); }
Float32Sqrt(Node * a)361   Node* Float32Sqrt(Node* a) { return AddNode(machine()->Float32Sqrt(), a); }
Float32Equal(Node * a,Node * b)362   Node* Float32Equal(Node* a, Node* b) {
363     return AddNode(machine()->Float32Equal(), a, b);
364   }
Float32NotEqual(Node * a,Node * b)365   Node* Float32NotEqual(Node* a, Node* b) {
366     return WordBinaryNot(Float32Equal(a, b));
367   }
Float32LessThan(Node * a,Node * b)368   Node* Float32LessThan(Node* a, Node* b) {
369     return AddNode(machine()->Float32LessThan(), a, b);
370   }
Float32LessThanOrEqual(Node * a,Node * b)371   Node* Float32LessThanOrEqual(Node* a, Node* b) {
372     return AddNode(machine()->Float32LessThanOrEqual(), a, b);
373   }
Float32GreaterThan(Node * a,Node * b)374   Node* Float32GreaterThan(Node* a, Node* b) { return Float32LessThan(b, a); }
Float32GreaterThanOrEqual(Node * a,Node * b)375   Node* Float32GreaterThanOrEqual(Node* a, Node* b) {
376     return Float32LessThanOrEqual(b, a);
377   }
378 
Float64Add(Node * a,Node * b)379   Node* Float64Add(Node* a, Node* b) {
380     return AddNode(machine()->Float64Add(), a, b);
381   }
Float64Sub(Node * a,Node * b)382   Node* Float64Sub(Node* a, Node* b) {
383     return AddNode(machine()->Float64Sub(), a, b);
384   }
Float64Mul(Node * a,Node * b)385   Node* Float64Mul(Node* a, Node* b) {
386     return AddNode(machine()->Float64Mul(), a, b);
387   }
Float64Div(Node * a,Node * b)388   Node* Float64Div(Node* a, Node* b) {
389     return AddNode(machine()->Float64Div(), a, b);
390   }
Float64Mod(Node * a,Node * b)391   Node* Float64Mod(Node* a, Node* b) {
392     return AddNode(machine()->Float64Mod(), a, b);
393   }
Float64Max(Node * a,Node * b)394   Node* Float64Max(Node* a, Node* b) {
395     return AddNode(machine()->Float64Max().op(), a, b);
396   }
Float64Min(Node * a,Node * b)397   Node* Float64Min(Node* a, Node* b) {
398     return AddNode(machine()->Float64Min().op(), a, b);
399   }
Float64Abs(Node * a)400   Node* Float64Abs(Node* a) { return AddNode(machine()->Float64Abs(), a); }
Float64Sqrt(Node * a)401   Node* Float64Sqrt(Node* a) { return AddNode(machine()->Float64Sqrt(), a); }
Float64Equal(Node * a,Node * b)402   Node* Float64Equal(Node* a, Node* b) {
403     return AddNode(machine()->Float64Equal(), a, b);
404   }
Float64NotEqual(Node * a,Node * b)405   Node* Float64NotEqual(Node* a, Node* b) {
406     return WordBinaryNot(Float64Equal(a, b));
407   }
Float64LessThan(Node * a,Node * b)408   Node* Float64LessThan(Node* a, Node* b) {
409     return AddNode(machine()->Float64LessThan(), a, b);
410   }
Float64LessThanOrEqual(Node * a,Node * b)411   Node* Float64LessThanOrEqual(Node* a, Node* b) {
412     return AddNode(machine()->Float64LessThanOrEqual(), a, b);
413   }
Float64GreaterThan(Node * a,Node * b)414   Node* Float64GreaterThan(Node* a, Node* b) { return Float64LessThan(b, a); }
Float64GreaterThanOrEqual(Node * a,Node * b)415   Node* Float64GreaterThanOrEqual(Node* a, Node* b) {
416     return Float64LessThanOrEqual(b, a);
417   }
418 
419   // Conversions.
ChangeFloat32ToFloat64(Node * a)420   Node* ChangeFloat32ToFloat64(Node* a) {
421     return AddNode(machine()->ChangeFloat32ToFloat64(), a);
422   }
ChangeInt32ToFloat64(Node * a)423   Node* ChangeInt32ToFloat64(Node* a) {
424     return AddNode(machine()->ChangeInt32ToFloat64(), a);
425   }
ChangeUint32ToFloat64(Node * a)426   Node* ChangeUint32ToFloat64(Node* a) {
427     return AddNode(machine()->ChangeUint32ToFloat64(), a);
428   }
ChangeFloat64ToInt32(Node * a)429   Node* ChangeFloat64ToInt32(Node* a) {
430     return AddNode(machine()->ChangeFloat64ToInt32(), a);
431   }
ChangeFloat64ToUint32(Node * a)432   Node* ChangeFloat64ToUint32(Node* a) {
433     return AddNode(machine()->ChangeFloat64ToUint32(), a);
434   }
TruncateFloat32ToInt64(Node * a)435   Node* TruncateFloat32ToInt64(Node* a) {
436     // TODO(ahaas): Remove this function as soon as it is not used anymore in
437     // WebAssembly.
438     return AddNode(machine()->TryTruncateFloat32ToInt64(), a);
439   }
TryTruncateFloat32ToInt64(Node * a)440   Node* TryTruncateFloat32ToInt64(Node* a) {
441     return AddNode(machine()->TryTruncateFloat32ToInt64(), a);
442   }
TruncateFloat64ToInt64(Node * a)443   Node* TruncateFloat64ToInt64(Node* a) {
444     // TODO(ahaas): Remove this function as soon as it is not used anymore in
445     // WebAssembly.
446     return AddNode(machine()->TryTruncateFloat64ToInt64(), a);
447   }
TryTruncateFloat64ToInt64(Node * a)448   Node* TryTruncateFloat64ToInt64(Node* a) {
449     return AddNode(machine()->TryTruncateFloat64ToInt64(), a);
450   }
TruncateFloat32ToUint64(Node * a)451   Node* TruncateFloat32ToUint64(Node* a) {
452     // TODO(ahaas): Remove this function as soon as it is not used anymore in
453     // WebAssembly.
454     return AddNode(machine()->TryTruncateFloat32ToUint64(), a);
455   }
TryTruncateFloat32ToUint64(Node * a)456   Node* TryTruncateFloat32ToUint64(Node* a) {
457     return AddNode(machine()->TryTruncateFloat32ToUint64(), a);
458   }
TruncateFloat64ToUint64(Node * a)459   Node* TruncateFloat64ToUint64(Node* a) {
460     // TODO(ahaas): Remove this function as soon as it is not used anymore in
461     // WebAssembly.
462     return AddNode(machine()->TryTruncateFloat64ToUint64(), a);
463   }
TryTruncateFloat64ToUint64(Node * a)464   Node* TryTruncateFloat64ToUint64(Node* a) {
465     return AddNode(machine()->TryTruncateFloat64ToUint64(), a);
466   }
ChangeInt32ToInt64(Node * a)467   Node* ChangeInt32ToInt64(Node* a) {
468     return AddNode(machine()->ChangeInt32ToInt64(), a);
469   }
ChangeUint32ToUint64(Node * a)470   Node* ChangeUint32ToUint64(Node* a) {
471     return AddNode(machine()->ChangeUint32ToUint64(), a);
472   }
TruncateFloat64ToFloat32(Node * a)473   Node* TruncateFloat64ToFloat32(Node* a) {
474     return AddNode(machine()->TruncateFloat64ToFloat32(), a);
475   }
TruncateFloat64ToInt32(TruncationMode mode,Node * a)476   Node* TruncateFloat64ToInt32(TruncationMode mode, Node* a) {
477     return AddNode(machine()->TruncateFloat64ToInt32(mode), a);
478   }
TruncateInt64ToInt32(Node * a)479   Node* TruncateInt64ToInt32(Node* a) {
480     return AddNode(machine()->TruncateInt64ToInt32(), a);
481   }
RoundInt64ToFloat32(Node * a)482   Node* RoundInt64ToFloat32(Node* a) {
483     return AddNode(machine()->RoundInt64ToFloat32(), a);
484   }
RoundInt64ToFloat64(Node * a)485   Node* RoundInt64ToFloat64(Node* a) {
486     return AddNode(machine()->RoundInt64ToFloat64(), a);
487   }
RoundUint64ToFloat32(Node * a)488   Node* RoundUint64ToFloat32(Node* a) {
489     return AddNode(machine()->RoundUint64ToFloat32(), a);
490   }
RoundUint64ToFloat64(Node * a)491   Node* RoundUint64ToFloat64(Node* a) {
492     return AddNode(machine()->RoundUint64ToFloat64(), a);
493   }
BitcastFloat32ToInt32(Node * a)494   Node* BitcastFloat32ToInt32(Node* a) {
495     return AddNode(machine()->BitcastFloat32ToInt32(), a);
496   }
BitcastFloat64ToInt64(Node * a)497   Node* BitcastFloat64ToInt64(Node* a) {
498     return AddNode(machine()->BitcastFloat64ToInt64(), a);
499   }
BitcastInt32ToFloat32(Node * a)500   Node* BitcastInt32ToFloat32(Node* a) {
501     return AddNode(machine()->BitcastInt32ToFloat32(), a);
502   }
BitcastInt64ToFloat64(Node * a)503   Node* BitcastInt64ToFloat64(Node* a) {
504     return AddNode(machine()->BitcastInt64ToFloat64(), a);
505   }
Float32RoundDown(Node * a)506   Node* Float32RoundDown(Node* a) {
507     return AddNode(machine()->Float32RoundDown().op(), a);
508   }
Float64RoundDown(Node * a)509   Node* Float64RoundDown(Node* a) {
510     return AddNode(machine()->Float64RoundDown().op(), a);
511   }
Float32RoundUp(Node * a)512   Node* Float32RoundUp(Node* a) {
513     return AddNode(machine()->Float32RoundUp().op(), a);
514   }
Float64RoundUp(Node * a)515   Node* Float64RoundUp(Node* a) {
516     return AddNode(machine()->Float64RoundUp().op(), a);
517   }
Float32RoundTruncate(Node * a)518   Node* Float32RoundTruncate(Node* a) {
519     return AddNode(machine()->Float32RoundTruncate().op(), a);
520   }
Float64RoundTruncate(Node * a)521   Node* Float64RoundTruncate(Node* a) {
522     return AddNode(machine()->Float64RoundTruncate().op(), a);
523   }
Float64RoundTiesAway(Node * a)524   Node* Float64RoundTiesAway(Node* a) {
525     return AddNode(machine()->Float64RoundTiesAway().op(), a);
526   }
Float32RoundTiesEven(Node * a)527   Node* Float32RoundTiesEven(Node* a) {
528     return AddNode(machine()->Float32RoundTiesEven().op(), a);
529   }
Float64RoundTiesEven(Node * a)530   Node* Float64RoundTiesEven(Node* a) {
531     return AddNode(machine()->Float64RoundTiesEven().op(), a);
532   }
533 
534   // Float64 bit operations.
Float64ExtractLowWord32(Node * a)535   Node* Float64ExtractLowWord32(Node* a) {
536     return AddNode(machine()->Float64ExtractLowWord32(), a);
537   }
Float64ExtractHighWord32(Node * a)538   Node* Float64ExtractHighWord32(Node* a) {
539     return AddNode(machine()->Float64ExtractHighWord32(), a);
540   }
Float64InsertLowWord32(Node * a,Node * b)541   Node* Float64InsertLowWord32(Node* a, Node* b) {
542     return AddNode(machine()->Float64InsertLowWord32(), a, b);
543   }
Float64InsertHighWord32(Node * a,Node * b)544   Node* Float64InsertHighWord32(Node* a, Node* b) {
545     return AddNode(machine()->Float64InsertHighWord32(), a, b);
546   }
547 
548   // Stack operations.
LoadStackPointer()549   Node* LoadStackPointer() { return AddNode(machine()->LoadStackPointer()); }
LoadFramePointer()550   Node* LoadFramePointer() { return AddNode(machine()->LoadFramePointer()); }
551 
552   // Parameters.
553   Node* Parameter(size_t index);
554 
555   // Pointer utilities.
556   Node* LoadFromPointer(void* address, MachineType rep, int32_t offset = 0) {
557     return Load(rep, PointerConstant(address), Int32Constant(offset));
558   }
StoreToPointer(void * address,MachineRepresentation rep,Node * node)559   Node* StoreToPointer(void* address, MachineRepresentation rep, Node* node) {
560     return Store(rep, PointerConstant(address), node, kNoWriteBarrier);
561   }
StringConstant(const char * string)562   Node* StringConstant(const char* string) {
563     return HeapConstant(isolate()->factory()->InternalizeUtf8String(string));
564   }
565 
566   // Call a given call descriptor and the given arguments.
567   Node* CallN(CallDescriptor* desc, Node* function, Node** args);
568   // Call a given call descriptor and the given arguments and frame-state.
569   Node* CallNWithFrameState(CallDescriptor* desc, Node* function, Node** args,
570                             Node* frame_state);
571   // Call to a runtime function with one arguments.
572   Node* CallRuntime1(Runtime::FunctionId function, Node* arg0, Node* context);
573   // Call to a runtime function with two arguments.
574   Node* CallRuntime2(Runtime::FunctionId function, Node* arg1, Node* arg2,
575                      Node* context);
576   // Call to a runtime function with four arguments.
577   Node* CallRuntime4(Runtime::FunctionId function, Node* arg1, Node* arg2,
578                      Node* arg3, Node* arg4, Node* context);
579   // Call to a C function with zero arguments.
580   Node* CallCFunction0(MachineType return_type, Node* function);
581   // Call to a C function with one parameter.
582   Node* CallCFunction1(MachineType return_type, MachineType arg0_type,
583                        Node* function, Node* arg0);
584   // Call to a C function with two arguments.
585   Node* CallCFunction2(MachineType return_type, MachineType arg0_type,
586                        MachineType arg1_type, Node* function, Node* arg0,
587                        Node* arg1);
588   // Call to a C function with eight arguments.
589   Node* CallCFunction8(MachineType return_type, MachineType arg0_type,
590                        MachineType arg1_type, MachineType arg2_type,
591                        MachineType arg3_type, MachineType arg4_type,
592                        MachineType arg5_type, MachineType arg6_type,
593                        MachineType arg7_type, Node* function, Node* arg0,
594                        Node* arg1, Node* arg2, Node* arg3, Node* arg4,
595                        Node* arg5, Node* arg6, Node* arg7);
596 
597   // Tail call the given call descriptor and the given arguments.
598   Node* TailCallN(CallDescriptor* call_descriptor, Node* function, Node** args);
599   // Tail call to a runtime function with one argument.
600   Node* TailCallRuntime1(Runtime::FunctionId function, Node* arg0,
601                          Node* context);
602   // Tail call to a runtime function with two arguments.
603   Node* TailCallRuntime2(Runtime::FunctionId function, Node* arg1, Node* arg2,
604                          Node* context);
605 
606 
607   // ===========================================================================
608   // The following utility methods deal with control flow, hence might switch
609   // the current basic block or create new basic blocks for labels.
610 
611   // Control flow.
612   void Goto(RawMachineLabel* label);
613   void Branch(Node* condition, RawMachineLabel* true_val,
614               RawMachineLabel* false_val);
615   void Switch(Node* index, RawMachineLabel* default_label, int32_t* case_values,
616               RawMachineLabel** case_labels, size_t case_count);
617   void Return(Node* value);
618   void Return(Node* v1, Node* v2);
619   void Return(Node* v1, Node* v2, Node* v3);
620   void Bind(RawMachineLabel* label);
621   void Deoptimize(Node* state);
622 
623   // Variables.
Phi(MachineRepresentation rep,Node * n1,Node * n2)624   Node* Phi(MachineRepresentation rep, Node* n1, Node* n2) {
625     return AddNode(common()->Phi(rep, 2), n1, n2);
626   }
Phi(MachineRepresentation rep,Node * n1,Node * n2,Node * n3)627   Node* Phi(MachineRepresentation rep, Node* n1, Node* n2, Node* n3) {
628     return AddNode(common()->Phi(rep, 3), n1, n2, n3);
629   }
Phi(MachineRepresentation rep,Node * n1,Node * n2,Node * n3,Node * n4)630   Node* Phi(MachineRepresentation rep, Node* n1, Node* n2, Node* n3, Node* n4) {
631     return AddNode(common()->Phi(rep, 4), n1, n2, n3, n4);
632   }
633 
634   // ===========================================================================
635   // The following generic node creation methods can be used for operators that
636   // are not covered by the above utility methods. There should rarely be a need
637   // to do that outside of testing though.
638 
639   Node* AddNode(const Operator* op, int input_count, Node** inputs);
640 
AddNode(const Operator * op)641   Node* AddNode(const Operator* op) {
642     return AddNode(op, 0, static_cast<Node**>(nullptr));
643   }
644 
645   template <class... TArgs>
AddNode(const Operator * op,Node * n1,TArgs...args)646   Node* AddNode(const Operator* op, Node* n1, TArgs... args) {
647     Node* buffer[] = {n1, args...};
648     return AddNode(op, sizeof...(args) + 1, buffer);
649   }
650 
651  private:
652   Node* MakeNode(const Operator* op, int input_count, Node** inputs);
653   BasicBlock* Use(RawMachineLabel* label);
654   BasicBlock* EnsureBlock(RawMachineLabel* label);
655   BasicBlock* CurrentBlock();
656 
schedule()657   Schedule* schedule() { return schedule_; }
parameter_count()658   size_t parameter_count() const { return machine_sig()->parameter_count(); }
machine_sig()659   const MachineSignature* machine_sig() const {
660     return call_descriptor_->GetMachineSignature();
661   }
662 
663   Isolate* isolate_;
664   Graph* graph_;
665   Schedule* schedule_;
666   MachineOperatorBuilder machine_;
667   CommonOperatorBuilder common_;
668   CallDescriptor* call_descriptor_;
669   NodeVector parameters_;
670   BasicBlock* current_block_;
671 
672   DISALLOW_COPY_AND_ASSIGN(RawMachineAssembler);
673 };
674 
675 
676 class RawMachineLabel final {
677  public:
678   RawMachineLabel();
679   ~RawMachineLabel();
680 
681  private:
682   BasicBlock* block_;
683   bool used_;
684   bool bound_;
685   friend class RawMachineAssembler;
686   DISALLOW_COPY_AND_ASSIGN(RawMachineLabel);
687 };
688 
689 }  // namespace compiler
690 }  // namespace internal
691 }  // namespace v8
692 
693 #endif  // V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_
694