Home | History | Annotate | Download | only in compiler
      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);
    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