• 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