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 #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 
     22 namespace v8 {
     23 namespace internal {
     24 
     25 class Callable;
     26 class CallInterfaceDescriptor;
     27 class Isolate;
     28 class Factory;
     29 class Zone;
     30 
     31 namespace compiler {
     32 
     33 class CallDescriptor;
     34 class CodeAssemblerLabel;
     35 class CodeAssemblerVariable;
     36 class CodeAssemblerState;
     37 class Node;
     38 class RawMachineAssembler;
     39 class RawMachineLabel;
     40 
     41 typedef ZoneList<CodeAssemblerVariable*> CodeAssemblerVariableList;
     42 
     43 typedef 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.
    189 class 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 
    416 class 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 
    436 class 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 
    477 class 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