• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
10  // Clients of this interface shouldn't depend on lots of compiler internals.
11  // Do not include anything from src/compiler here!
12  #include "src/allocation.h"
13  #include "src/builtins.h"
14  #include "src/heap/heap.h"
15  #include "src/machine-type.h"
16  #include "src/runtime/runtime.h"
17  #include "src/zone-containers.h"
18  
19  namespace v8 {
20  namespace internal {
21  
22  class Callable;
23  class CallInterfaceDescriptor;
24  class Isolate;
25  class Factory;
26  class Zone;
27  
28  namespace compiler {
29  
30  class CallDescriptor;
31  class Graph;
32  class Node;
33  class Operator;
34  class RawMachineAssembler;
35  class RawMachineLabel;
36  class Schedule;
37  
38  #define CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
39    V(Float32Equal)                                \
40    V(Float32LessThan)                             \
41    V(Float32LessThanOrEqual)                      \
42    V(Float32GreaterThan)                          \
43    V(Float32GreaterThanOrEqual)                   \
44    V(Float64Equal)                                \
45    V(Float64LessThan)                             \
46    V(Float64LessThanOrEqual)                      \
47    V(Float64GreaterThan)                          \
48    V(Float64GreaterThanOrEqual)                   \
49    V(Int32GreaterThan)                            \
50    V(Int32GreaterThanOrEqual)                     \
51    V(Int32LessThan)                               \
52    V(Int32LessThanOrEqual)                        \
53    V(IntPtrLessThan)                              \
54    V(IntPtrLessThanOrEqual)                       \
55    V(IntPtrGreaterThan)                           \
56    V(IntPtrGreaterThanOrEqual)                    \
57    V(IntPtrEqual)                                 \
58    V(Uint32LessThan)                              \
59    V(UintPtrLessThan)                             \
60    V(UintPtrGreaterThanOrEqual)                   \
61    V(WordEqual)                                   \
62    V(WordNotEqual)                                \
63    V(Word32Equal)                                 \
64    V(Word32NotEqual)                              \
65    V(Word64Equal)                                 \
66    V(Word64NotEqual)
67  
68  #define CODE_ASSEMBLER_BINARY_OP_LIST(V)   \
69    CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
70    V(Float64Add)                            \
71    V(Float64Sub)                            \
72    V(Float64Mul)                            \
73    V(Float64Div)                            \
74    V(Float64Mod)                            \
75    V(Float64Atan2)                          \
76    V(Float64InsertLowWord32)                \
77    V(Float64InsertHighWord32)               \
78    V(IntPtrAdd)                             \
79    V(IntPtrAddWithOverflow)                 \
80    V(IntPtrSub)                             \
81    V(IntPtrSubWithOverflow)                 \
82    V(IntPtrMul)                             \
83    V(Int32Add)                              \
84    V(Int32AddWithOverflow)                  \
85    V(Int32Sub)                              \
86    V(Int32Mul)                              \
87    V(Int32Div)                              \
88    V(WordOr)                                \
89    V(WordAnd)                               \
90    V(WordXor)                               \
91    V(WordShl)                               \
92    V(WordShr)                               \
93    V(WordSar)                               \
94    V(WordRor)                               \
95    V(Word32Or)                              \
96    V(Word32And)                             \
97    V(Word32Xor)                             \
98    V(Word32Shl)                             \
99    V(Word32Shr)                             \
100    V(Word32Sar)                             \
101    V(Word32Ror)                             \
102    V(Word64Or)                              \
103    V(Word64And)                             \
104    V(Word64Xor)                             \
105    V(Word64Shr)                             \
106    V(Word64Sar)                             \
107    V(Word64Ror)
108  
109  #define CODE_ASSEMBLER_UNARY_OP_LIST(V) \
110    V(Float64Atan)                        \
111    V(Float64Atanh)                       \
112    V(Float64Cos)                         \
113    V(Float64Exp)                         \
114    V(Float64Expm1)                       \
115    V(Float64Log)                         \
116    V(Float64Log1p)                       \
117    V(Float64Log2)                        \
118    V(Float64Log10)                       \
119    V(Float64Cbrt)                        \
120    V(Float64Neg)                         \
121    V(Float64Sin)                         \
122    V(Float64Sqrt)                        \
123    V(Float64Tan)                         \
124    V(Float64ExtractLowWord32)            \
125    V(Float64ExtractHighWord32)           \
126    V(BitcastWordToTagged)                \
127    V(TruncateFloat64ToWord32)            \
128    V(TruncateInt64ToInt32)               \
129    V(ChangeFloat64ToUint32)              \
130    V(ChangeInt32ToFloat64)               \
131    V(ChangeInt32ToInt64)                 \
132    V(ChangeUint32ToFloat64)              \
133    V(ChangeUint32ToUint64)               \
134    V(RoundFloat64ToInt32)                \
135    V(Float64RoundDown)                   \
136    V(Float64RoundUp)                     \
137    V(Float64RoundTruncate)               \
138    V(Word32Clz)
139  
140  // A "public" interface used by components outside of compiler directory to
141  // create code objects with TurboFan's backend. This class is mostly a thin shim
142  // around the RawMachineAssembler, and its primary job is to ensure that the
143  // innards of the RawMachineAssembler and other compiler implementation details
144  // don't leak outside of the the compiler directory..
145  //
146  // V8 components that need to generate low-level code using this interface
147  // should include this header--and this header only--from the compiler directory
148  // (this is actually enforced). Since all interesting data structures are
149  // forward declared, it's not possible for clients to peek inside the compiler
150  // internals.
151  //
152  // In addition to providing isolation between TurboFan and code generation
153  // clients, CodeAssembler also provides an abstraction for creating variables
154  // and enhanced Label functionality to merge variable values along paths where
155  // they have differing values, including loops.
156  class CodeAssembler {
157   public:
158    // Create with CallStub linkage.
159    // |result_size| specifies the number of results returned by the stub.
160    // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
161    CodeAssembler(Isolate* isolate, Zone* zone,
162                  const CallInterfaceDescriptor& descriptor, Code::Flags flags,
163                  const char* name, size_t result_size = 1);
164  
165    // Create with JSCall linkage.
166    CodeAssembler(Isolate* isolate, Zone* zone, int parameter_count,
167                  Code::Flags flags, const char* name);
168  
169    virtual ~CodeAssembler();
170  
171    Handle<Code> GenerateCode();
172  
173    bool Is64() const;
174    bool IsFloat64RoundUpSupported() const;
175    bool IsFloat64RoundDownSupported() const;
176    bool IsFloat64RoundTruncateSupported() const;
177  
178    class Label;
179    class Variable {
180     public:
181      explicit Variable(CodeAssembler* assembler, MachineRepresentation rep);
182      ~Variable();
183      void Bind(Node* value);
184      Node* value() const;
185      MachineRepresentation rep() const;
186      bool IsBound() const;
187  
188     private:
189      friend class CodeAssembler;
190      class Impl;
191      Impl* impl_;
192      CodeAssembler* assembler_;
193    };
194  
195    enum AllocationFlag : uint8_t {
196      kNone = 0,
197      kDoubleAlignment = 1,
198      kPretenured = 1 << 1
199    };
200  
201    typedef base::Flags<AllocationFlag> AllocationFlags;
202  
203    // ===========================================================================
204    // Base Assembler
205    // ===========================================================================
206  
207    // Constants.
208    Node* Int32Constant(int32_t value);
209    Node* Int64Constant(int64_t value);
210    Node* IntPtrConstant(intptr_t value);
211    Node* NumberConstant(double value);
212    Node* SmiConstant(Smi* value);
213    Node* HeapConstant(Handle<HeapObject> object);
214    Node* BooleanConstant(bool value);
215    Node* ExternalConstant(ExternalReference address);
216    Node* Float64Constant(double value);
217    Node* NaNConstant();
218  
219    bool ToInt32Constant(Node* node, int32_t& out_value);
220    bool ToInt64Constant(Node* node, int64_t& out_value);
221    bool ToIntPtrConstant(Node* node, intptr_t& out_value);
222  
223    Node* Parameter(int value);
224    void Return(Node* value);
225  
226    void DebugBreak();
227    void Comment(const char* format, ...);
228  
229    void Bind(Label* label);
230    void Goto(Label* label);
231    void GotoIf(Node* condition, Label* true_label);
232    void GotoUnless(Node* condition, Label* false_label);
233    void Branch(Node* condition, Label* true_label, Label* false_label);
234  
235    void Switch(Node* index, Label* default_label, int32_t* case_values,
236                Label** case_labels, size_t case_count);
237  
238    // Access to the frame pointer
239    Node* LoadFramePointer();
240    Node* LoadParentFramePointer();
241  
242    // Access to the stack pointer
243    Node* LoadStackPointer();
244  
245    // Load raw memory location.
246    Node* Load(MachineType rep, Node* base);
247    Node* Load(MachineType rep, Node* base, Node* index);
248    Node* AtomicLoad(MachineType rep, Node* base, Node* index);
249  
250    // Load a value from the root array.
251    Node* LoadRoot(Heap::RootListIndex root_index);
252  
253    // Store value to raw memory location.
254    Node* Store(MachineRepresentation rep, Node* base, Node* value);
255    Node* Store(MachineRepresentation rep, Node* base, Node* index, Node* value);
256    Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* value);
257    Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* index,
258                              Node* value);
259    Node* AtomicStore(MachineRepresentation rep, Node* base, Node* index,
260                      Node* value);
261  
262    // Store a value to the root array.
263    Node* StoreRoot(Heap::RootListIndex root_index, Node* value);
264  
265  // Basic arithmetic operations.
266  #define DECLARE_CODE_ASSEMBLER_BINARY_OP(name) Node* name(Node* a, Node* b);
267    CODE_ASSEMBLER_BINARY_OP_LIST(DECLARE_CODE_ASSEMBLER_BINARY_OP)
268  #undef DECLARE_CODE_ASSEMBLER_BINARY_OP
269  
270    Node* WordShl(Node* value, int shift);
271    Node* WordShr(Node* value, int shift);
272  
273  // Unary
274  #define DECLARE_CODE_ASSEMBLER_UNARY_OP(name) Node* name(Node* a);
275    CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)
276  #undef DECLARE_CODE_ASSEMBLER_UNARY_OP
277  
278    // No-op on 32-bit, otherwise zero extend.
279    Node* ChangeUint32ToWord(Node* value);
280    // No-op on 32-bit, otherwise sign extend.
281    Node* ChangeInt32ToIntPtr(Node* value);
282  
283    // Projections
284    Node* Projection(int index, Node* value);
285  
286    // Calls
287    Node* CallRuntime(Runtime::FunctionId function_id, Node* context);
288    Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1);
289    Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
290                      Node* arg2);
291    Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
292                      Node* arg2, Node* arg3);
293    Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
294                      Node* arg2, Node* arg3, Node* arg4);
295    Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
296                      Node* arg2, Node* arg3, Node* arg4, Node* arg5);
297  
298    Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context);
299    Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
300                          Node* arg1);
301    Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
302                          Node* arg1, Node* arg2);
303    Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
304                          Node* arg1, Node* arg2, Node* arg3);
305    Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
306                          Node* arg1, Node* arg2, Node* arg3, Node* arg4);
307  
308    Node* CallStub(Callable const& callable, Node* context, Node* arg1,
309                   size_t result_size = 1);
310    Node* CallStub(Callable const& callable, Node* context, Node* arg1,
311                   Node* arg2, size_t result_size = 1);
312    Node* CallStub(Callable const& callable, Node* context, Node* arg1,
313                   Node* arg2, Node* arg3, size_t result_size = 1);
314    Node* CallStubN(Callable const& callable, Node** args,
315                    size_t result_size = 1);
316  
317    Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
318                   Node* context, Node* arg1, size_t result_size = 1);
319    Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
320                   Node* context, Node* arg1, Node* arg2, size_t result_size = 1);
321    Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
322                   Node* context, Node* arg1, Node* arg2, Node* arg3,
323                   size_t result_size = 1);
324    Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
325                   Node* context, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
326                   size_t result_size = 1);
327    Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
328                   Node* context, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
329                   Node* arg5, size_t result_size = 1);
330    Node* CallStubN(const CallInterfaceDescriptor& descriptor, Node* target,
331                    Node** args, size_t result_size = 1);
332  
333    Node* TailCallStub(Callable const& callable, Node* context, Node* arg1,
334                       Node* arg2, size_t result_size = 1);
335    Node* TailCallStub(Callable const& callable, Node* context, Node* arg1,
336                       Node* arg2, Node* arg3, size_t result_size = 1);
337    Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
338                       Node* context, Node* arg1, Node* arg2,
339                       size_t result_size = 1);
340    Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
341                       Node* context, Node* arg1, Node* arg2, Node* arg3,
342                       size_t result_size = 1);
343    Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
344                       Node* context, Node* arg1, Node* arg2, Node* arg3,
345                       Node* arg4, size_t result_size = 1);
346  
347    Node* TailCallBytecodeDispatch(const CallInterfaceDescriptor& descriptor,
348                                   Node* code_target_address, Node** args);
349  
350    Node* CallJS(Callable const& callable, Node* context, Node* function,
351                 Node* receiver, size_t result_size = 1);
352    Node* CallJS(Callable const& callable, Node* context, Node* function,
353                 Node* receiver, Node* arg1, size_t result_size = 1);
354    Node* CallJS(Callable const& callable, Node* context, Node* function,
355                 Node* receiver, Node* arg1, Node* arg2, size_t result_size = 1);
356  
357    // Branching helpers.
358    void BranchIf(Node* condition, Label* if_true, Label* if_false);
359  
360  #define BRANCH_HELPER(name)                                                \
361    void BranchIf##name(Node* a, Node* b, Label* if_true, Label* if_false) { \
362      BranchIf(name(a, b), if_true, if_false);                               \
363    }
364    CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(BRANCH_HELPER)
365  #undef BRANCH_HELPER
366  
367    // Helpers which delegate to RawMachineAssembler.
368    Factory* factory() const;
369    Isolate* isolate() const;
370    Zone* zone() const;
371  
372   protected:
373    // Protected helpers which delegate to RawMachineAssembler.
374    Graph* graph() const;
375  
376    Node* SmiShiftBitsConstant();
377  
378    // Enables subclasses to perform operations before and after a call.
379    virtual void CallPrologue();
380    virtual void CallEpilogue();
381  
382   private:
383    CodeAssembler(Isolate* isolate, Zone* zone, CallDescriptor* call_descriptor,
384                  Code::Flags flags, const char* name);
385  
386    Node* CallN(CallDescriptor* descriptor, Node* code_target, Node** args);
387    Node* TailCallN(CallDescriptor* descriptor, Node* code_target, Node** args);
388  
389    base::SmartPointer<RawMachineAssembler> raw_assembler_;
390    Code::Flags flags_;
391    const char* name_;
392    bool code_generated_;
393    ZoneSet<Variable::Impl*> variables_;
394  
395    DISALLOW_COPY_AND_ASSIGN(CodeAssembler);
396  };
397  
398  DEFINE_OPERATORS_FOR_FLAGS(CodeAssembler::AllocationFlags);
399  
400  class CodeAssembler::Label {
401   public:
402    enum Type { kDeferred, kNonDeferred };
403  
404    explicit Label(
405        CodeAssembler* assembler,
406        CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred)
407        : CodeAssembler::Label(assembler, 0, nullptr, type) {}
408    Label(CodeAssembler* assembler, CodeAssembler::Variable* merged_variable,
409          CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred)
410        : CodeAssembler::Label(assembler, 1, &merged_variable, type) {}
411    Label(CodeAssembler* assembler, int merged_variable_count,
412          CodeAssembler::Variable** merged_variables,
413          CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred);
~Label()414    ~Label() {}
415  
416   private:
417    friend class CodeAssembler;
418  
419    void Bind();
420    void MergeVariables();
421  
422    bool bound_;
423    size_t merge_count_;
424    CodeAssembler* assembler_;
425    RawMachineLabel* label_;
426    // Map of variables that need to be merged to their phi nodes (or placeholders
427    // for those phis).
428    std::map<Variable::Impl*, Node*> variable_phis_;
429    // Map of variables to the list of value nodes that have been added from each
430    // merge path in their order of merging.
431    std::map<Variable::Impl*, std::vector<Node*>> variable_merges_;
432  };
433  
434  }  // namespace compiler
435  }  // namespace internal
436  }  // namespace v8
437  
438  #endif  // V8_COMPILER_CODE_ASSEMBLER_H_
439