1// Copyright 2015 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_CODE_ASSEMBLER_H_
6#define V8_COMPILER_CODE_ASSEMBLER_H_
7
8#include <map>
9#include <memory>
10
11// Clients of this interface shouldn't depend on lots of compiler internals.
12// Do not include anything from src/compiler here!
13#include "src/allocation.h"
14#include "src/builtins/builtins.h"
15#include "src/code-factory.h"
16#include "src/globals.h"
17#include "src/heap/heap.h"
18#include "src/machine-type.h"
19#include "src/runtime/runtime.h"
20#include "src/zone/zone-containers.h"
21
22namespace v8 {
23namespace internal {
24
25class Callable;
26class CallInterfaceDescriptor;
27class Isolate;
28class Factory;
29class Zone;
30
31namespace compiler {
32
33class CallDescriptor;
34class CodeAssemblerLabel;
35class CodeAssemblerVariable;
36class CodeAssemblerState;
37class Node;
38class RawMachineAssembler;
39class RawMachineLabel;
40
41typedef ZoneList<CodeAssemblerVariable*> CodeAssemblerVariableList;
42
43typedef std::function<void()> CodeAssemblerCallback;
44
45#define CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
46  V(Float32Equal)                                \
47  V(Float32LessThan)                             \
48  V(Float32LessThanOrEqual)                      \
49  V(Float32GreaterThan)                          \
50  V(Float32GreaterThanOrEqual)                   \
51  V(Float64Equal)                                \
52  V(Float64LessThan)                             \
53  V(Float64LessThanOrEqual)                      \
54  V(Float64GreaterThan)                          \
55  V(Float64GreaterThanOrEqual)                   \
56  V(Int32GreaterThan)                            \
57  V(Int32GreaterThanOrEqual)                     \
58  V(Int32LessThan)                               \
59  V(Int32LessThanOrEqual)                        \
60  V(IntPtrLessThan)                              \
61  V(IntPtrLessThanOrEqual)                       \
62  V(IntPtrGreaterThan)                           \
63  V(IntPtrGreaterThanOrEqual)                    \
64  V(IntPtrEqual)                                 \
65  V(Uint32LessThan)                              \
66  V(Uint32LessThanOrEqual)                       \
67  V(Uint32GreaterThanOrEqual)                    \
68  V(UintPtrLessThan)                             \
69  V(UintPtrLessThanOrEqual)                      \
70  V(UintPtrGreaterThan)                          \
71  V(UintPtrGreaterThanOrEqual)                   \
72  V(WordEqual)                                   \
73  V(WordNotEqual)                                \
74  V(Word32Equal)                                 \
75  V(Word32NotEqual)                              \
76  V(Word64Equal)                                 \
77  V(Word64NotEqual)
78
79#define CODE_ASSEMBLER_BINARY_OP_LIST(V)   \
80  CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
81  V(Float64Add)                            \
82  V(Float64Sub)                            \
83  V(Float64Mul)                            \
84  V(Float64Div)                            \
85  V(Float64Mod)                            \
86  V(Float64Atan2)                          \
87  V(Float64Pow)                            \
88  V(Float64InsertLowWord32)                \
89  V(Float64InsertHighWord32)               \
90  V(IntPtrAddWithOverflow)                 \
91  V(IntPtrSubWithOverflow)                 \
92  V(IntPtrMul)                             \
93  V(Int32Add)                              \
94  V(Int32AddWithOverflow)                  \
95  V(Int32Sub)                              \
96  V(Int32Mul)                              \
97  V(Int32MulWithOverflow)                  \
98  V(Int32Div)                              \
99  V(Int32Mod)                              \
100  V(WordOr)                                \
101  V(WordAnd)                               \
102  V(WordXor)                               \
103  V(WordShl)                               \
104  V(WordShr)                               \
105  V(WordSar)                               \
106  V(WordRor)                               \
107  V(Word32Or)                              \
108  V(Word32And)                             \
109  V(Word32Xor)                             \
110  V(Word32Shl)                             \
111  V(Word32Shr)                             \
112  V(Word32Sar)                             \
113  V(Word32Ror)                             \
114  V(Word64Or)                              \
115  V(Word64And)                             \
116  V(Word64Xor)                             \
117  V(Word64Shr)                             \
118  V(Word64Sar)                             \
119  V(Word64Ror)
120
121#define CODE_ASSEMBLER_UNARY_OP_LIST(V) \
122  V(Float64Abs)                         \
123  V(Float64Acos)                        \
124  V(Float64Acosh)                       \
125  V(Float64Asin)                        \
126  V(Float64Asinh)                       \
127  V(Float64Atan)                        \
128  V(Float64Atanh)                       \
129  V(Float64Cos)                         \
130  V(Float64Cosh)                        \
131  V(Float64Exp)                         \
132  V(Float64Expm1)                       \
133  V(Float64Log)                         \
134  V(Float64Log1p)                       \
135  V(Float64Log2)                        \
136  V(Float64Log10)                       \
137  V(Float64Cbrt)                        \
138  V(Float64Neg)                         \
139  V(Float64Sin)                         \
140  V(Float64Sinh)                        \
141  V(Float64Sqrt)                        \
142  V(Float64Tan)                         \
143  V(Float64Tanh)                        \
144  V(Float64ExtractLowWord32)            \
145  V(Float64ExtractHighWord32)           \
146  V(BitcastTaggedToWord)                \
147  V(BitcastWordToTagged)                \
148  V(BitcastWordToTaggedSigned)          \
149  V(TruncateFloat64ToFloat32)           \
150  V(TruncateFloat64ToWord32)            \
151  V(TruncateInt64ToInt32)               \
152  V(ChangeFloat32ToFloat64)             \
153  V(ChangeFloat64ToUint32)              \
154  V(ChangeInt32ToFloat64)               \
155  V(ChangeInt32ToInt64)                 \
156  V(ChangeUint32ToFloat64)              \
157  V(ChangeUint32ToUint64)               \
158  V(RoundFloat64ToInt32)                \
159  V(RoundInt32ToFloat32)                \
160  V(Float64SilenceNaN)                  \
161  V(Float64RoundDown)                   \
162  V(Float64RoundUp)                     \
163  V(Float64RoundTiesEven)               \
164  V(Float64RoundTruncate)               \
165  V(Word32Clz)                          \
166  V(Word32Not)                          \
167  V(Word32BinaryNot)
168
169// A "public" interface used by components outside of compiler directory to
170// create code objects with TurboFan's backend. This class is mostly a thin shim
171// around the RawMachineAssembler, and its primary job is to ensure that the
172// innards of the RawMachineAssembler and other compiler implementation details
173// don't leak outside of the the compiler directory..
174//
175// V8 components that need to generate low-level code using this interface
176// should include this header--and this header only--from the compiler directory
177// (this is actually enforced). Since all interesting data structures are
178// forward declared, it's not possible for clients to peek inside the compiler
179// internals.
180//
181// In addition to providing isolation between TurboFan and code generation
182// clients, CodeAssembler also provides an abstraction for creating variables
183// and enhanced Label functionality to merge variable values along paths where
184// they have differing values, including loops.
185//
186// The CodeAssembler itself is stateless (and instances are expected to be
187// temporary-scoped and short-lived); all its state is encapsulated into
188// a CodeAssemblerState instance.
189class V8_EXPORT_PRIVATE CodeAssembler {
190 public:
191  explicit CodeAssembler(CodeAssemblerState* state) : state_(state) {}
192  ~CodeAssembler();
193
194  static Handle<Code> GenerateCode(CodeAssemblerState* state);
195
196  bool Is64() const;
197  bool IsFloat64RoundUpSupported() const;
198  bool IsFloat64RoundDownSupported() const;
199  bool IsFloat64RoundTiesEvenSupported() const;
200  bool IsFloat64RoundTruncateSupported() const;
201
202  // Shortened aliases for use in CodeAssembler subclasses.
203  typedef CodeAssemblerLabel Label;
204  typedef CodeAssemblerVariable Variable;
205  typedef CodeAssemblerVariableList VariableList;
206
207  // ===========================================================================
208  // Base Assembler
209  // ===========================================================================
210
211  // Constants.
212  Node* Int32Constant(int32_t value);
213  Node* Int64Constant(int64_t value);
214  Node* IntPtrConstant(intptr_t value);
215  Node* NumberConstant(double value);
216  Node* SmiConstant(Smi* value);
217  Node* SmiConstant(int value);
218  Node* HeapConstant(Handle<HeapObject> object);
219  Node* CStringConstant(const char* str);
220  Node* BooleanConstant(bool value);
221  Node* ExternalConstant(ExternalReference address);
222  Node* Float64Constant(double value);
223  Node* NaNConstant();
224
225  bool ToInt32Constant(Node* node, int32_t& out_value);
226  bool ToInt64Constant(Node* node, int64_t& out_value);
227  bool ToSmiConstant(Node* node, Smi*& out_value);
228  bool ToIntPtrConstant(Node* node, intptr_t& out_value);
229
230  Node* Parameter(int value);
231  Node* GetJSContextParameter();
232  void Return(Node* value);
233  void Return(Node* value1, Node* value2);
234  void Return(Node* value1, Node* value2, Node* value3);
235  void PopAndReturn(Node* pop, Node* value);
236
237  void DebugBreak();
238  void Unreachable();
239  void Comment(const char* format, ...);
240
241  void Bind(Label* label);
242  void Goto(Label* label);
243  void GotoIf(Node* condition, Label* true_label);
244  void GotoIfNot(Node* condition, Label* false_label);
245  void Branch(Node* condition, Label* true_label, Label* false_label);
246
247  void Switch(Node* index, Label* default_label, const int32_t* case_values,
248              Label** case_labels, size_t case_count);
249
250  // Access to the frame pointer
251  Node* LoadFramePointer();
252  Node* LoadParentFramePointer();
253
254  // Access to the stack pointer
255  Node* LoadStackPointer();
256
257  // Load raw memory location.
258  Node* Load(MachineType rep, Node* base);
259  Node* Load(MachineType rep, Node* base, Node* offset);
260  Node* AtomicLoad(MachineType rep, Node* base, Node* offset);
261
262  // Load a value from the root array.
263  Node* LoadRoot(Heap::RootListIndex root_index);
264
265  // Store value to raw memory location.
266  Node* Store(Node* base, Node* value);
267  Node* Store(Node* base, Node* offset, Node* value);
268  Node* StoreWithMapWriteBarrier(Node* base, Node* offset, Node* value);
269  Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* value);
270  Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* offset,
271                            Node* value);
272  Node* AtomicStore(MachineRepresentation rep, Node* base, Node* offset,
273                    Node* value);
274
275  // Store a value to the root array.
276  Node* StoreRoot(Heap::RootListIndex root_index, Node* value);
277
278// Basic arithmetic operations.
279#define DECLARE_CODE_ASSEMBLER_BINARY_OP(name) Node* name(Node* a, Node* b);
280  CODE_ASSEMBLER_BINARY_OP_LIST(DECLARE_CODE_ASSEMBLER_BINARY_OP)
281#undef DECLARE_CODE_ASSEMBLER_BINARY_OP
282
283  Node* IntPtrAdd(Node* left, Node* right);
284  Node* IntPtrSub(Node* left, Node* right);
285
286  Node* WordShl(Node* value, int shift);
287  Node* WordShr(Node* value, int shift);
288  Node* Word32Shr(Node* value, int shift);
289
290// Unary
291#define DECLARE_CODE_ASSEMBLER_UNARY_OP(name) Node* name(Node* a);
292  CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)
293#undef DECLARE_CODE_ASSEMBLER_UNARY_OP
294
295  // Changes an intptr_t to a double, e.g. for storing an element index
296  // outside Smi range in a HeapNumber. Lossless on 32-bit,
297  // rounds on 64-bit (which doesn't affect valid element indices).
298  Node* RoundIntPtrToFloat64(Node* value);
299  // No-op on 32-bit, otherwise zero extend.
300  Node* ChangeUint32ToWord(Node* value);
301  // No-op on 32-bit, otherwise sign extend.
302  Node* ChangeInt32ToIntPtr(Node* value);
303
304  // No-op that guarantees that the value is kept alive till this point even
305  // if GC happens.
306  Node* Retain(Node* value);
307
308  // Projections
309  Node* Projection(int index, Node* value);
310
311  // Calls
312  template <class... TArgs>
313  Node* CallRuntime(Runtime::FunctionId function, Node* context, TArgs... args);
314
315  template <class... TArgs>
316  Node* TailCallRuntime(Runtime::FunctionId function, Node* context,
317                        TArgs... args);
318
319  template <class... TArgs>
320  Node* CallStub(Callable const& callable, Node* context, TArgs... args) {
321    Node* target = HeapConstant(callable.code());
322    return CallStub(callable.descriptor(), target, context, args...);
323  }
324
325  template <class... TArgs>
326  Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
327                 Node* context, TArgs... args) {
328    return CallStubR(descriptor, 1, target, context, args...);
329  }
330
331  template <class... TArgs>
332  Node* CallStubR(const CallInterfaceDescriptor& descriptor, size_t result_size,
333                  Node* target, Node* context, TArgs... args);
334
335  Node* CallStubN(const CallInterfaceDescriptor& descriptor, size_t result_size,
336                  int input_count, Node* const* inputs);
337
338  template <class... TArgs>
339  Node* TailCallStub(Callable const& callable, Node* context, TArgs... args) {
340    Node* target = HeapConstant(callable.code());
341    return TailCallStub(callable.descriptor(), target, context, args...);
342  }
343
344  template <class... TArgs>
345  Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
346                     Node* context, TArgs... args);
347
348  template <class... TArgs>
349  Node* TailCallBytecodeDispatch(const CallInterfaceDescriptor& descriptor,
350                                 Node* target, TArgs... args);
351
352  template <class... TArgs>
353  Node* CallJS(Callable const& callable, Node* context, Node* function,
354               Node* receiver, TArgs... args) {
355    int argc = static_cast<int>(sizeof...(args));
356    Node* arity = Int32Constant(argc);
357    return CallStub(callable, context, function, arity, receiver, args...);
358  }
359
360  template <class... TArgs>
361  Node* ConstructJS(Callable const& callable, Node* context, Node* new_target,
362                    TArgs... args) {
363    int argc = static_cast<int>(sizeof...(args));
364    Node* arity = Int32Constant(argc);
365    Node* receiver = LoadRoot(Heap::kUndefinedValueRootIndex);
366
367    // Construct(target, new_target, arity, receiver, arguments...)
368    return CallStub(callable, context, new_target, new_target, arity, receiver,
369                    args...);
370  }
371
372  Node* CallCFunctionN(Signature<MachineType>* signature, int input_count,
373                       Node* const* inputs);
374
375  // Call to a C function with two arguments.
376  Node* CallCFunction2(MachineType return_type, MachineType arg0_type,
377                       MachineType arg1_type, Node* function, Node* arg0,
378                       Node* arg1);
379
380  // Call to a C function with three arguments.
381  Node* CallCFunction3(MachineType return_type, MachineType arg0_type,
382                       MachineType arg1_type, MachineType arg2_type,
383                       Node* function, Node* arg0, Node* arg1, Node* arg2);
384
385  // Exception handling support.
386  void GotoIfException(Node* node, Label* if_exception,
387                       Variable* exception_var = nullptr);
388
389  // Helpers which delegate to RawMachineAssembler.
390  Factory* factory() const;
391  Isolate* isolate() const;
392  Zone* zone() const;
393
394  CodeAssemblerState* state() { return state_; }
395
396  void BreakOnNode(int node_id);
397
398 protected:
399  void RegisterCallGenerationCallbacks(
400      const CodeAssemblerCallback& call_prologue,
401      const CodeAssemblerCallback& call_epilogue);
402  void UnregisterCallGenerationCallbacks();
403
404 private:
405  RawMachineAssembler* raw_assembler() const;
406
407  // Calls respective callback registered in the state.
408  void CallPrologue();
409  void CallEpilogue();
410
411  CodeAssemblerState* state_;
412
413  DISALLOW_COPY_AND_ASSIGN(CodeAssembler);
414};
415
416class CodeAssemblerVariable {
417 public:
418  explicit CodeAssemblerVariable(CodeAssembler* assembler,
419                                 MachineRepresentation rep);
420  CodeAssemblerVariable(CodeAssembler* assembler, MachineRepresentation rep,
421                        Node* initial_value);
422  ~CodeAssemblerVariable();
423  void Bind(Node* value);
424  Node* value() const;
425  MachineRepresentation rep() const;
426  bool IsBound() const;
427
428 private:
429  friend class CodeAssemblerLabel;
430  friend class CodeAssemblerState;
431  class Impl;
432  Impl* impl_;
433  CodeAssemblerState* state_;
434};
435
436class CodeAssemblerLabel {
437 public:
438  enum Type { kDeferred, kNonDeferred };
439
440  explicit CodeAssemblerLabel(
441      CodeAssembler* assembler,
442      CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
443      : CodeAssemblerLabel(assembler, 0, nullptr, type) {}
444  CodeAssemblerLabel(
445      CodeAssembler* assembler,
446      const CodeAssemblerVariableList& merged_variables,
447      CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
448      : CodeAssemblerLabel(assembler, merged_variables.length(),
449                           &(merged_variables[0]), type) {}
450  CodeAssemblerLabel(
451      CodeAssembler* assembler, size_t count, CodeAssemblerVariable** vars,
452      CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred);
453  CodeAssemblerLabel(
454      CodeAssembler* assembler, CodeAssemblerVariable* merged_variable,
455      CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
456      : CodeAssemblerLabel(assembler, 1, &merged_variable, type) {}
457  ~CodeAssemblerLabel();
458
459 private:
460  friend class CodeAssembler;
461
462  void Bind();
463  void MergeVariables();
464
465  bool bound_;
466  size_t merge_count_;
467  CodeAssemblerState* state_;
468  RawMachineLabel* label_;
469  // Map of variables that need to be merged to their phi nodes (or placeholders
470  // for those phis).
471  std::map<CodeAssemblerVariable::Impl*, Node*> variable_phis_;
472  // Map of variables to the list of value nodes that have been added from each
473  // merge path in their order of merging.
474  std::map<CodeAssemblerVariable::Impl*, std::vector<Node*>> variable_merges_;
475};
476
477class V8_EXPORT_PRIVATE CodeAssemblerState {
478 public:
479  // Create with CallStub linkage.
480  // |result_size| specifies the number of results returned by the stub.
481  // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
482  CodeAssemblerState(Isolate* isolate, Zone* zone,
483                     const CallInterfaceDescriptor& descriptor,
484                     Code::Flags flags, const char* name,
485                     size_t result_size = 1);
486
487  // Create with JSCall linkage.
488  CodeAssemblerState(Isolate* isolate, Zone* zone, int parameter_count,
489                     Code::Flags flags, const char* name);
490
491  ~CodeAssemblerState();
492
493  const char* name() const { return name_; }
494  int parameter_count() const;
495
496 private:
497  friend class CodeAssembler;
498  friend class CodeAssemblerLabel;
499  friend class CodeAssemblerVariable;
500
501  CodeAssemblerState(Isolate* isolate, Zone* zone,
502                     CallDescriptor* call_descriptor, Code::Flags flags,
503                     const char* name);
504
505  std::unique_ptr<RawMachineAssembler> raw_assembler_;
506  Code::Flags flags_;
507  const char* name_;
508  bool code_generated_;
509  ZoneSet<CodeAssemblerVariable::Impl*> variables_;
510  CodeAssemblerCallback call_prologue_;
511  CodeAssemblerCallback call_epilogue_;
512
513  DISALLOW_COPY_AND_ASSIGN(CodeAssemblerState);
514};
515
516}  // namespace compiler
517}  // namespace internal
518}  // namespace v8
519
520#endif  // V8_COMPILER_CODE_ASSEMBLER_H_
521