raw-machine-assembler.h revision bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8
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
17namespace v8 {
18namespace internal {
19namespace compiler {
20
21class BasicBlock;
22class RawMachineLabel;
23class 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.
37class 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);
44  ~RawMachineAssembler() {}
45
46  Isolate* isolate() const { return isolate_; }
47  Graph* graph() const { return graph_; }
48  Zone* zone() const { return graph()->zone(); }
49  MachineOperatorBuilder* machine() { return &machine_; }
50  CommonOperatorBuilder* common() { return &common_; }
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
62  Node* NullConstant() {
63    return HeapConstant(isolate()->factory()->null_value());
64  }
65
66  Node* UndefinedConstant() {
67    return HeapConstant(isolate()->factory()->undefined_value());
68  }
69
70  // Constants.
71  Node* PointerConstant(void* value) {
72    return IntPtrConstant(reinterpret_cast<intptr_t>(value));
73  }
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  }
79  Node* RelocatableIntPtrConstant(intptr_t value, RelocInfo::Mode rmode);
80  Node* Int32Constant(int32_t value) {
81    return AddNode(common()->Int32Constant(value));
82  }
83  Node* StackSlot(MachineRepresentation rep) {
84    return AddNode(machine()->StackSlot(rep));
85  }
86  Node* Int64Constant(int64_t value) {
87    return AddNode(common()->Int64Constant(value));
88  }
89  Node* NumberConstant(double value) {
90    return AddNode(common()->NumberConstant(value));
91  }
92  Node* Float32Constant(float value) {
93    return AddNode(common()->Float32Constant(value));
94  }
95  Node* Float64Constant(double value) {
96    return AddNode(common()->Float64Constant(value));
97  }
98  Node* HeapConstant(Handle<HeapObject> object) {
99    return AddNode(common()->HeapConstant(object));
100  }
101  Node* BooleanConstant(bool value) {
102    Handle<Object> object = isolate()->factory()->ToBoolean(value);
103    return HeapConstant(Handle<HeapObject>::cast(object));
104  }
105  Node* ExternalConstant(ExternalReference address) {
106    return AddNode(common()->ExternalConstant(address));
107  }
108  Node* RelocatableInt32Constant(int32_t value, RelocInfo::Mode rmode) {
109    return AddNode(common()->RelocatableInt32Constant(value, rmode));
110  }
111  Node* RelocatableInt64Constant(int64_t value, RelocInfo::Mode rmode) {
112    return AddNode(common()->RelocatableInt64Constant(value, rmode));
113  }
114
115  Node* Projection(int index, Node* a) {
116    return AddNode(common()->Projection(index), a);
117  }
118
119  // Memory Operations.
120  Node* Load(MachineType rep, Node* base) {
121    return Load(rep, base, IntPtrConstant(0));
122  }
123  Node* Load(MachineType rep, Node* base, Node* index) {
124    return AddNode(machine()->Load(rep), base, index);
125  }
126  Node* Store(MachineRepresentation rep, Node* base, Node* value,
127              WriteBarrierKind write_barrier) {
128    return Store(rep, base, IntPtrConstant(0), value, write_barrier);
129  }
130  Node* Store(MachineRepresentation rep, Node* base, Node* index, Node* value,
131              WriteBarrierKind write_barrier) {
132    return AddNode(machine()->Store(StoreRepresentation(rep, write_barrier)),
133                   base, index, value);
134  }
135
136  // Atomic memory operations.
137  Node* AtomicLoad(MachineType rep, Node* base, Node* index) {
138    return AddNode(machine()->AtomicLoad(rep), base, index);
139  }
140  Node* AtomicStore(MachineRepresentation rep, Node* base, Node* index,
141                    Node* value) {
142    return AddNode(machine()->AtomicStore(rep), base, index, value);
143  }
144
145  // Arithmetic Operations.
146  Node* WordAnd(Node* a, Node* b) {
147    return AddNode(machine()->WordAnd(), a, b);
148  }
149  Node* WordOr(Node* a, Node* b) { return AddNode(machine()->WordOr(), a, b); }
150  Node* WordXor(Node* a, Node* b) {
151    return AddNode(machine()->WordXor(), a, b);
152  }
153  Node* WordShl(Node* a, Node* b) {
154    return AddNode(machine()->WordShl(), a, b);
155  }
156  Node* WordShr(Node* a, Node* b) {
157    return AddNode(machine()->WordShr(), a, b);
158  }
159  Node* WordSar(Node* a, Node* b) {
160    return AddNode(machine()->WordSar(), a, b);
161  }
162  Node* WordRor(Node* a, Node* b) {
163    return AddNode(machine()->WordRor(), a, b);
164  }
165  Node* WordEqual(Node* a, Node* b) {
166    return AddNode(machine()->WordEqual(), a, b);
167  }
168  Node* WordNotEqual(Node* a, Node* b) {
169    return Word32BinaryNot(WordEqual(a, b));
170  }
171  Node* WordNot(Node* a) {
172    if (machine()->Is32()) {
173      return Word32Not(a);
174    } else {
175      return Word64Not(a);
176    }
177  }
178
179  Node* Word32And(Node* a, Node* b) {
180    return AddNode(machine()->Word32And(), a, b);
181  }
182  Node* Word32Or(Node* a, Node* b) {
183    return AddNode(machine()->Word32Or(), a, b);
184  }
185  Node* Word32Xor(Node* a, Node* b) {
186    return AddNode(machine()->Word32Xor(), a, b);
187  }
188  Node* Word32Shl(Node* a, Node* b) {
189    return AddNode(machine()->Word32Shl(), a, b);
190  }
191  Node* Word32Shr(Node* a, Node* b) {
192    return AddNode(machine()->Word32Shr(), a, b);
193  }
194  Node* Word32Sar(Node* a, Node* b) {
195    return AddNode(machine()->Word32Sar(), a, b);
196  }
197  Node* Word32Ror(Node* a, Node* b) {
198    return AddNode(machine()->Word32Ror(), a, b);
199  }
200  Node* Word32Clz(Node* a) { return AddNode(machine()->Word32Clz(), a); }
201  Node* Word32Equal(Node* a, Node* b) {
202    return AddNode(machine()->Word32Equal(), a, b);
203  }
204  Node* Word32NotEqual(Node* a, Node* b) {
205    return Word32BinaryNot(Word32Equal(a, b));
206  }
207  Node* Word32Not(Node* a) { return Word32Xor(a, Int32Constant(-1)); }
208  Node* Word32BinaryNot(Node* a) { return Word32Equal(a, Int32Constant(0)); }
209
210  Node* Word64And(Node* a, Node* b) {
211    return AddNode(machine()->Word64And(), a, b);
212  }
213  Node* Word64Or(Node* a, Node* b) {
214    return AddNode(machine()->Word64Or(), a, b);
215  }
216  Node* Word64Xor(Node* a, Node* b) {
217    return AddNode(machine()->Word64Xor(), a, b);
218  }
219  Node* Word64Shl(Node* a, Node* b) {
220    return AddNode(machine()->Word64Shl(), a, b);
221  }
222  Node* Word64Shr(Node* a, Node* b) {
223    return AddNode(machine()->Word64Shr(), a, b);
224  }
225  Node* Word64Sar(Node* a, Node* b) {
226    return AddNode(machine()->Word64Sar(), a, b);
227  }
228  Node* Word64Ror(Node* a, Node* b) {
229    return AddNode(machine()->Word64Ror(), a, b);
230  }
231  Node* Word64Clz(Node* a) { return AddNode(machine()->Word64Clz(), a); }
232  Node* Word64Equal(Node* a, Node* b) {
233    return AddNode(machine()->Word64Equal(), a, b);
234  }
235  Node* Word64NotEqual(Node* a, Node* b) {
236    return Word32BinaryNot(Word64Equal(a, b));
237  }
238  Node* Word64Not(Node* a) { return Word64Xor(a, Int64Constant(-1)); }
239
240  Node* Int32Add(Node* a, Node* b) {
241    return AddNode(machine()->Int32Add(), a, b);
242  }
243  Node* Int32AddWithOverflow(Node* a, Node* b) {
244    return AddNode(machine()->Int32AddWithOverflow(), a, b);
245  }
246  Node* Int32Sub(Node* a, Node* b) {
247    return AddNode(machine()->Int32Sub(), a, b);
248  }
249  Node* Int32SubWithOverflow(Node* a, Node* b) {
250    return AddNode(machine()->Int32SubWithOverflow(), a, b);
251  }
252  Node* Int32Mul(Node* a, Node* b) {
253    return AddNode(machine()->Int32Mul(), a, b);
254  }
255  Node* Int32MulHigh(Node* a, Node* b) {
256    return AddNode(machine()->Int32MulHigh(), a, b);
257  }
258  Node* Int32Div(Node* a, Node* b) {
259    return AddNode(machine()->Int32Div(), a, b);
260  }
261  Node* Int32Mod(Node* a, Node* b) {
262    return AddNode(machine()->Int32Mod(), a, b);
263  }
264  Node* Int32LessThan(Node* a, Node* b) {
265    return AddNode(machine()->Int32LessThan(), a, b);
266  }
267  Node* Int32LessThanOrEqual(Node* a, Node* b) {
268    return AddNode(machine()->Int32LessThanOrEqual(), a, b);
269  }
270  Node* Uint32Div(Node* a, Node* b) {
271    return AddNode(machine()->Uint32Div(), a, b);
272  }
273  Node* Uint32LessThan(Node* a, Node* b) {
274    return AddNode(machine()->Uint32LessThan(), a, b);
275  }
276  Node* Uint32LessThanOrEqual(Node* a, Node* b) {
277    return AddNode(machine()->Uint32LessThanOrEqual(), a, b);
278  }
279  Node* Uint32Mod(Node* a, Node* b) {
280    return AddNode(machine()->Uint32Mod(), a, b);
281  }
282  Node* Uint32MulHigh(Node* a, Node* b) {
283    return AddNode(machine()->Uint32MulHigh(), a, b);
284  }
285  Node* Int32GreaterThan(Node* a, Node* b) { return Int32LessThan(b, a); }
286  Node* Int32GreaterThanOrEqual(Node* a, Node* b) {
287    return Int32LessThanOrEqual(b, a);
288  }
289  Node* Uint32GreaterThan(Node* a, Node* b) { return Uint32LessThan(b, a); }
290  Node* Uint32GreaterThanOrEqual(Node* a, Node* b) {
291    return Uint32LessThanOrEqual(b, a);
292  }
293  Node* Int32Neg(Node* a) { return Int32Sub(Int32Constant(0), a); }
294
295  Node* Int64Add(Node* a, Node* b) {
296    return AddNode(machine()->Int64Add(), a, b);
297  }
298  Node* Int64AddWithOverflow(Node* a, Node* b) {
299    return AddNode(machine()->Int64AddWithOverflow(), a, b);
300  }
301  Node* Int64Sub(Node* a, Node* b) {
302    return AddNode(machine()->Int64Sub(), a, b);
303  }
304  Node* Int64SubWithOverflow(Node* a, Node* b) {
305    return AddNode(machine()->Int64SubWithOverflow(), a, b);
306  }
307  Node* Int64Mul(Node* a, Node* b) {
308    return AddNode(machine()->Int64Mul(), a, b);
309  }
310  Node* Int64Div(Node* a, Node* b) {
311    return AddNode(machine()->Int64Div(), a, b);
312  }
313  Node* Int64Mod(Node* a, Node* b) {
314    return AddNode(machine()->Int64Mod(), a, b);
315  }
316  Node* Int64Neg(Node* a) { return Int64Sub(Int64Constant(0), a); }
317  Node* Int64LessThan(Node* a, Node* b) {
318    return AddNode(machine()->Int64LessThan(), a, b);
319  }
320  Node* Int64LessThanOrEqual(Node* a, Node* b) {
321    return AddNode(machine()->Int64LessThanOrEqual(), a, b);
322  }
323  Node* Uint64LessThan(Node* a, Node* b) {
324    return AddNode(machine()->Uint64LessThan(), a, b);
325  }
326  Node* Uint64LessThanOrEqual(Node* a, Node* b) {
327    return AddNode(machine()->Uint64LessThanOrEqual(), a, b);
328  }
329  Node* Int64GreaterThan(Node* a, Node* b) { return Int64LessThan(b, a); }
330  Node* Int64GreaterThanOrEqual(Node* a, Node* b) {
331    return Int64LessThanOrEqual(b, a);
332  }
333  Node* Uint64GreaterThan(Node* a, Node* b) { return Uint64LessThan(b, a); }
334  Node* Uint64GreaterThanOrEqual(Node* a, Node* b) {
335    return Uint64LessThanOrEqual(b, a);
336  }
337  Node* Uint64Div(Node* a, Node* b) {
338    return AddNode(machine()->Uint64Div(), a, b);
339  }
340  Node* Uint64Mod(Node* a, Node* b) {
341    return AddNode(machine()->Uint64Mod(), a, b);
342  }
343  Node* Int32PairAdd(Node* a_low, Node* a_high, Node* b_low, Node* b_high) {
344    return AddNode(machine()->Int32PairAdd(), a_low, a_high, b_low, b_high);
345  }
346  Node* Int32PairSub(Node* a_low, Node* a_high, Node* b_low, Node* b_high) {
347    return AddNode(machine()->Int32PairSub(), a_low, a_high, b_low, b_high);
348  }
349  Node* Int32PairMul(Node* a_low, Node* a_high, Node* b_low, Node* b_high) {
350    return AddNode(machine()->Int32PairMul(), a_low, a_high, b_low, b_high);
351  }
352  Node* Word32PairShl(Node* low_word, Node* high_word, Node* shift) {
353    return AddNode(machine()->Word32PairShl(), low_word, high_word, shift);
354  }
355  Node* Word32PairShr(Node* low_word, Node* high_word, Node* shift) {
356    return AddNode(machine()->Word32PairShr(), low_word, high_word, shift);
357  }
358  Node* Word32PairSar(Node* low_word, Node* high_word, Node* shift) {
359    return AddNode(machine()->Word32PairSar(), low_word, high_word, shift);
360  }
361
362#define INTPTR_BINOP(prefix, name)                     \
363  Node* IntPtr##name(Node* a, Node* b) {               \
364    return kPointerSize == 8 ? prefix##64##name(a, b)  \
365                             : prefix##32##name(a, b); \
366  }
367
368  INTPTR_BINOP(Int, Add);
369  INTPTR_BINOP(Int, AddWithOverflow);
370  INTPTR_BINOP(Int, Sub);
371  INTPTR_BINOP(Int, SubWithOverflow);
372  INTPTR_BINOP(Int, Mul);
373  INTPTR_BINOP(Int, Div);
374  INTPTR_BINOP(Int, LessThan);
375  INTPTR_BINOP(Int, LessThanOrEqual);
376  INTPTR_BINOP(Word, Equal);
377  INTPTR_BINOP(Word, NotEqual);
378  INTPTR_BINOP(Int, GreaterThanOrEqual);
379  INTPTR_BINOP(Int, GreaterThan);
380
381#undef INTPTR_BINOP
382
383#define UINTPTR_BINOP(prefix, name)                    \
384  Node* UintPtr##name(Node* a, Node* b) {              \
385    return kPointerSize == 8 ? prefix##64##name(a, b)  \
386                             : prefix##32##name(a, b); \
387  }
388
389  UINTPTR_BINOP(Uint, LessThan);
390  UINTPTR_BINOP(Uint, LessThanOrEqual);
391  UINTPTR_BINOP(Uint, GreaterThanOrEqual);
392  UINTPTR_BINOP(Uint, GreaterThan);
393
394#undef UINTPTR_BINOP
395
396  Node* Float32Add(Node* a, Node* b) {
397    return AddNode(machine()->Float32Add(), a, b);
398  }
399  Node* Float32Sub(Node* a, Node* b) {
400    return AddNode(machine()->Float32Sub(), a, b);
401  }
402  Node* Float32SubPreserveNan(Node* a, Node* b) {
403    return AddNode(machine()->Float32SubPreserveNan(), a, b);
404  }
405  Node* Float32Mul(Node* a, Node* b) {
406    return AddNode(machine()->Float32Mul(), a, b);
407  }
408  Node* Float32Div(Node* a, Node* b) {
409    return AddNode(machine()->Float32Div(), a, b);
410  }
411  Node* Float32Max(Node* a, Node* b) {
412    return AddNode(machine()->Float32Max().op(), a, b);
413  }
414  Node* Float32Min(Node* a, Node* b) {
415    return AddNode(machine()->Float32Min().op(), a, b);
416  }
417  Node* Float32Abs(Node* a) { return AddNode(machine()->Float32Abs(), a); }
418  Node* Float32Neg(Node* a) { return Float32Sub(Float32Constant(-0.0f), a); }
419  Node* Float32Sqrt(Node* a) { return AddNode(machine()->Float32Sqrt(), a); }
420  Node* Float32Equal(Node* a, Node* b) {
421    return AddNode(machine()->Float32Equal(), a, b);
422  }
423  Node* Float32NotEqual(Node* a, Node* b) {
424    return Word32BinaryNot(Float32Equal(a, b));
425  }
426  Node* Float32LessThan(Node* a, Node* b) {
427    return AddNode(machine()->Float32LessThan(), a, b);
428  }
429  Node* Float32LessThanOrEqual(Node* a, Node* b) {
430    return AddNode(machine()->Float32LessThanOrEqual(), a, b);
431  }
432  Node* Float32GreaterThan(Node* a, Node* b) { return Float32LessThan(b, a); }
433  Node* Float32GreaterThanOrEqual(Node* a, Node* b) {
434    return Float32LessThanOrEqual(b, a);
435  }
436
437  Node* Float64Add(Node* a, Node* b) {
438    return AddNode(machine()->Float64Add(), a, b);
439  }
440  Node* Float64Sub(Node* a, Node* b) {
441    return AddNode(machine()->Float64Sub(), a, b);
442  }
443  Node* Float64SubPreserveNan(Node* a, Node* b) {
444    return AddNode(machine()->Float64SubPreserveNan(), a, b);
445  }
446  Node* Float64Mul(Node* a, Node* b) {
447    return AddNode(machine()->Float64Mul(), a, b);
448  }
449  Node* Float64Div(Node* a, Node* b) {
450    return AddNode(machine()->Float64Div(), a, b);
451  }
452  Node* Float64Mod(Node* a, Node* b) {
453    return AddNode(machine()->Float64Mod(), a, b);
454  }
455  Node* Float64Max(Node* a, Node* b) {
456    return AddNode(machine()->Float64Max().op(), a, b);
457  }
458  Node* Float64Min(Node* a, Node* b) {
459    return AddNode(machine()->Float64Min().op(), a, b);
460  }
461  Node* Float64Abs(Node* a) { return AddNode(machine()->Float64Abs(), a); }
462  Node* Float64Neg(Node* a) { return Float64Sub(Float64Constant(-0.0), a); }
463  Node* Float64Sqrt(Node* a) { return AddNode(machine()->Float64Sqrt(), a); }
464  Node* Float64Equal(Node* a, Node* b) {
465    return AddNode(machine()->Float64Equal(), a, b);
466  }
467  Node* Float64NotEqual(Node* a, Node* b) {
468    return Word32BinaryNot(Float64Equal(a, b));
469  }
470  Node* Float64LessThan(Node* a, Node* b) {
471    return AddNode(machine()->Float64LessThan(), a, b);
472  }
473  Node* Float64LessThanOrEqual(Node* a, Node* b) {
474    return AddNode(machine()->Float64LessThanOrEqual(), a, b);
475  }
476  Node* Float64GreaterThan(Node* a, Node* b) { return Float64LessThan(b, a); }
477  Node* Float64GreaterThanOrEqual(Node* a, Node* b) {
478    return Float64LessThanOrEqual(b, a);
479  }
480
481  // Conversions.
482  Node* BitcastWordToTagged(Node* a) {
483    return AddNode(machine()->BitcastWordToTagged(), a);
484  }
485  Node* TruncateFloat64ToWord32(Node* a) {
486    return AddNode(machine()->TruncateFloat64ToWord32(), a);
487  }
488  Node* ChangeFloat32ToFloat64(Node* a) {
489    return AddNode(machine()->ChangeFloat32ToFloat64(), a);
490  }
491  Node* ChangeInt32ToFloat64(Node* a) {
492    return AddNode(machine()->ChangeInt32ToFloat64(), a);
493  }
494  Node* ChangeUint32ToFloat64(Node* a) {
495    return AddNode(machine()->ChangeUint32ToFloat64(), a);
496  }
497  Node* ChangeFloat64ToInt32(Node* a) {
498    return AddNode(machine()->ChangeFloat64ToInt32(), a);
499  }
500  Node* ChangeFloat64ToUint32(Node* a) {
501    return AddNode(machine()->ChangeFloat64ToUint32(), a);
502  }
503  Node* TruncateFloat64ToUint32(Node* a) {
504    return AddNode(machine()->TruncateFloat64ToUint32(), a);
505  }
506  Node* TruncateFloat32ToInt32(Node* a) {
507    return AddNode(machine()->TruncateFloat32ToInt32(), a);
508  }
509  Node* TruncateFloat32ToUint32(Node* a) {
510    return AddNode(machine()->TruncateFloat32ToUint32(), a);
511  }
512  Node* TryTruncateFloat32ToInt64(Node* a) {
513    return AddNode(machine()->TryTruncateFloat32ToInt64(), a);
514  }
515  Node* TryTruncateFloat64ToInt64(Node* a) {
516    return AddNode(machine()->TryTruncateFloat64ToInt64(), a);
517  }
518  Node* TryTruncateFloat32ToUint64(Node* a) {
519    return AddNode(machine()->TryTruncateFloat32ToUint64(), a);
520  }
521  Node* TryTruncateFloat64ToUint64(Node* a) {
522    return AddNode(machine()->TryTruncateFloat64ToUint64(), a);
523  }
524  Node* ChangeInt32ToInt64(Node* a) {
525    return AddNode(machine()->ChangeInt32ToInt64(), a);
526  }
527  Node* ChangeUint32ToUint64(Node* a) {
528    return AddNode(machine()->ChangeUint32ToUint64(), a);
529  }
530  Node* TruncateFloat64ToFloat32(Node* a) {
531    return AddNode(machine()->TruncateFloat64ToFloat32(), a);
532  }
533  Node* TruncateInt64ToInt32(Node* a) {
534    return AddNode(machine()->TruncateInt64ToInt32(), a);
535  }
536  Node* RoundFloat64ToInt32(Node* a) {
537    return AddNode(machine()->RoundFloat64ToInt32(), a);
538  }
539  Node* RoundInt32ToFloat32(Node* a) {
540    return AddNode(machine()->RoundInt32ToFloat32(), a);
541  }
542  Node* RoundInt64ToFloat32(Node* a) {
543    return AddNode(machine()->RoundInt64ToFloat32(), a);
544  }
545  Node* RoundInt64ToFloat64(Node* a) {
546    return AddNode(machine()->RoundInt64ToFloat64(), a);
547  }
548  Node* RoundUint32ToFloat32(Node* a) {
549    return AddNode(machine()->RoundUint32ToFloat32(), a);
550  }
551  Node* RoundUint64ToFloat32(Node* a) {
552    return AddNode(machine()->RoundUint64ToFloat32(), a);
553  }
554  Node* RoundUint64ToFloat64(Node* a) {
555    return AddNode(machine()->RoundUint64ToFloat64(), a);
556  }
557  Node* BitcastFloat32ToInt32(Node* a) {
558    return AddNode(machine()->BitcastFloat32ToInt32(), a);
559  }
560  Node* BitcastFloat64ToInt64(Node* a) {
561    return AddNode(machine()->BitcastFloat64ToInt64(), a);
562  }
563  Node* BitcastInt32ToFloat32(Node* a) {
564    return AddNode(machine()->BitcastInt32ToFloat32(), a);
565  }
566  Node* BitcastInt64ToFloat64(Node* a) {
567    return AddNode(machine()->BitcastInt64ToFloat64(), a);
568  }
569  Node* Float32RoundDown(Node* a) {
570    return AddNode(machine()->Float32RoundDown().op(), a);
571  }
572  Node* Float64RoundDown(Node* a) {
573    return AddNode(machine()->Float64RoundDown().op(), a);
574  }
575  Node* Float32RoundUp(Node* a) {
576    return AddNode(machine()->Float32RoundUp().op(), a);
577  }
578  Node* Float64RoundUp(Node* a) {
579    return AddNode(machine()->Float64RoundUp().op(), a);
580  }
581  Node* Float32RoundTruncate(Node* a) {
582    return AddNode(machine()->Float32RoundTruncate().op(), a);
583  }
584  Node* Float64RoundTruncate(Node* a) {
585    return AddNode(machine()->Float64RoundTruncate().op(), a);
586  }
587  Node* Float64RoundTiesAway(Node* a) {
588    return AddNode(machine()->Float64RoundTiesAway().op(), a);
589  }
590  Node* Float32RoundTiesEven(Node* a) {
591    return AddNode(machine()->Float32RoundTiesEven().op(), a);
592  }
593  Node* Float64RoundTiesEven(Node* a) {
594    return AddNode(machine()->Float64RoundTiesEven().op(), a);
595  }
596
597  // Float64 bit operations.
598  Node* Float64ExtractLowWord32(Node* a) {
599    return AddNode(machine()->Float64ExtractLowWord32(), a);
600  }
601  Node* Float64ExtractHighWord32(Node* a) {
602    return AddNode(machine()->Float64ExtractHighWord32(), a);
603  }
604  Node* Float64InsertLowWord32(Node* a, Node* b) {
605    return AddNode(machine()->Float64InsertLowWord32(), a, b);
606  }
607  Node* Float64InsertHighWord32(Node* a, Node* b) {
608    return AddNode(machine()->Float64InsertHighWord32(), a, b);
609  }
610
611  // Stack operations.
612  Node* LoadStackPointer() { return AddNode(machine()->LoadStackPointer()); }
613  Node* LoadFramePointer() { return AddNode(machine()->LoadFramePointer()); }
614  Node* LoadParentFramePointer() {
615    return AddNode(machine()->LoadParentFramePointer());
616  }
617
618  // Parameters.
619  Node* Parameter(size_t index);
620
621  // Pointer utilities.
622  Node* LoadFromPointer(void* address, MachineType rep, int32_t offset = 0) {
623    return Load(rep, PointerConstant(address), Int32Constant(offset));
624  }
625  Node* StoreToPointer(void* address, MachineRepresentation rep, Node* node) {
626    return Store(rep, PointerConstant(address), node, kNoWriteBarrier);
627  }
628  Node* StringConstant(const char* string) {
629    return HeapConstant(isolate()->factory()->InternalizeUtf8String(string));
630  }
631
632  // Call a given call descriptor and the given arguments.
633  Node* CallN(CallDescriptor* desc, Node* function, Node** args);
634  // Call a given call descriptor and the given arguments and frame-state.
635  Node* CallNWithFrameState(CallDescriptor* desc, Node* function, Node** args,
636                            Node* frame_state);
637  // Call to a runtime function with zero arguments.
638  Node* CallRuntime0(Runtime::FunctionId function, Node* context);
639  // Call to a runtime function with one arguments.
640  Node* CallRuntime1(Runtime::FunctionId function, Node* arg0, Node* context);
641  // Call to a runtime function with two arguments.
642  Node* CallRuntime2(Runtime::FunctionId function, Node* arg1, Node* arg2,
643                     Node* context);
644  // Call to a runtime function with three arguments.
645  Node* CallRuntime3(Runtime::FunctionId function, Node* arg1, Node* arg2,
646                     Node* arg3, Node* context);
647  // Call to a runtime function with four arguments.
648  Node* CallRuntime4(Runtime::FunctionId function, Node* arg1, Node* arg2,
649                     Node* arg3, Node* arg4, Node* context);
650  // Call to a C function with zero arguments.
651  Node* CallCFunction0(MachineType return_type, Node* function);
652  // Call to a C function with one parameter.
653  Node* CallCFunction1(MachineType return_type, MachineType arg0_type,
654                       Node* function, Node* arg0);
655  // Call to a C function with two arguments.
656  Node* CallCFunction2(MachineType return_type, MachineType arg0_type,
657                       MachineType arg1_type, Node* function, Node* arg0,
658                       Node* arg1);
659  // Call to a C function with eight arguments.
660  Node* CallCFunction8(MachineType return_type, MachineType arg0_type,
661                       MachineType arg1_type, MachineType arg2_type,
662                       MachineType arg3_type, MachineType arg4_type,
663                       MachineType arg5_type, MachineType arg6_type,
664                       MachineType arg7_type, Node* function, Node* arg0,
665                       Node* arg1, Node* arg2, Node* arg3, Node* arg4,
666                       Node* arg5, Node* arg6, Node* arg7);
667
668  // Tail call the given call descriptor and the given arguments.
669  Node* TailCallN(CallDescriptor* call_descriptor, Node* function, Node** args);
670  // Tail call to a runtime function with zero arguments.
671  Node* TailCallRuntime0(Runtime::FunctionId function, Node* context);
672  // Tail call to a runtime function with one argument.
673  Node* TailCallRuntime1(Runtime::FunctionId function, Node* arg0,
674                         Node* context);
675  // Tail call to a runtime function with two arguments.
676  Node* TailCallRuntime2(Runtime::FunctionId function, Node* arg1, Node* arg2,
677                         Node* context);
678  // Tail call to a runtime function with three arguments.
679  Node* TailCallRuntime3(Runtime::FunctionId function, Node* arg1, Node* arg2,
680                         Node* arg3, Node* context);
681  // Tail call to a runtime function with four arguments.
682  Node* TailCallRuntime4(Runtime::FunctionId function, Node* arg1, Node* arg2,
683                         Node* arg3, Node* arg4, Node* context);
684
685  // ===========================================================================
686  // The following utility methods deal with control flow, hence might switch
687  // the current basic block or create new basic blocks for labels.
688
689  // Control flow.
690  void Goto(RawMachineLabel* label);
691  void Branch(Node* condition, RawMachineLabel* true_val,
692              RawMachineLabel* false_val);
693  void Switch(Node* index, RawMachineLabel* default_label, int32_t* case_values,
694              RawMachineLabel** case_labels, size_t case_count);
695  void Return(Node* value);
696  void Return(Node* v1, Node* v2);
697  void Return(Node* v1, Node* v2, Node* v3);
698  void Bind(RawMachineLabel* label);
699  void Deoptimize(Node* state);
700
701  // Variables.
702  Node* Phi(MachineRepresentation rep, Node* n1, Node* n2) {
703    return AddNode(common()->Phi(rep, 2), n1, n2, graph()->start());
704  }
705  Node* Phi(MachineRepresentation rep, Node* n1, Node* n2, Node* n3) {
706    return AddNode(common()->Phi(rep, 3), n1, n2, n3, graph()->start());
707  }
708  Node* Phi(MachineRepresentation rep, Node* n1, Node* n2, Node* n3, Node* n4) {
709    return AddNode(common()->Phi(rep, 4), n1, n2, n3, n4, graph()->start());
710  }
711  Node* Phi(MachineRepresentation rep, int input_count, Node* const* inputs);
712  void AppendPhiInput(Node* phi, Node* new_input);
713
714  // ===========================================================================
715  // The following generic node creation methods can be used for operators that
716  // are not covered by the above utility methods. There should rarely be a need
717  // to do that outside of testing though.
718
719  Node* AddNode(const Operator* op, int input_count, Node* const* inputs);
720
721  Node* AddNode(const Operator* op) {
722    return AddNode(op, 0, static_cast<Node* const*>(nullptr));
723  }
724
725  template <class... TArgs>
726  Node* AddNode(const Operator* op, Node* n1, TArgs... args) {
727    Node* buffer[] = {n1, args...};
728    return AddNode(op, sizeof...(args) + 1, buffer);
729  }
730
731 private:
732  Node* MakeNode(const Operator* op, int input_count, Node* const* inputs);
733  BasicBlock* Use(RawMachineLabel* label);
734  BasicBlock* EnsureBlock(RawMachineLabel* label);
735  BasicBlock* CurrentBlock();
736
737  Schedule* schedule() { return schedule_; }
738  size_t parameter_count() const { return machine_sig()->parameter_count(); }
739  const MachineSignature* machine_sig() const {
740    return call_descriptor_->GetMachineSignature();
741  }
742
743  Isolate* isolate_;
744  Graph* graph_;
745  Schedule* schedule_;
746  MachineOperatorBuilder machine_;
747  CommonOperatorBuilder common_;
748  CallDescriptor* call_descriptor_;
749  NodeVector parameters_;
750  BasicBlock* current_block_;
751
752  DISALLOW_COPY_AND_ASSIGN(RawMachineAssembler);
753};
754
755
756class RawMachineLabel final {
757 public:
758  enum Type { kDeferred, kNonDeferred };
759
760  explicit RawMachineLabel(Type type = kNonDeferred)
761      : deferred_(type == kDeferred) {}
762  ~RawMachineLabel();
763
764 private:
765  BasicBlock* block_ = nullptr;
766  bool used_ = false;
767  bool bound_ = false;
768  bool deferred_;
769  friend class RawMachineAssembler;
770  DISALLOW_COPY_AND_ASSIGN(RawMachineLabel);
771};
772
773}  // namespace compiler
774}  // namespace internal
775}  // namespace v8
776
777#endif  // V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_
778