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_WASM_COMPILER_H_
      6 #define V8_COMPILER_WASM_COMPILER_H_
      7 
      8 #include <memory>
      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/compilation-info.h"
     13 #include "src/compiler.h"
     14 #include "src/wasm/wasm-opcodes.h"
     15 #include "src/wasm/wasm-result.h"
     16 #include "src/zone/zone.h"
     17 
     18 namespace v8 {
     19 namespace internal {
     20 
     21 namespace compiler {
     22 // Forward declarations for some compiler data structures.
     23 class Node;
     24 class JSGraph;
     25 class Graph;
     26 class Operator;
     27 class SourcePositionTable;
     28 }  // namespace compiler
     29 
     30 namespace wasm {
     31 // Forward declarations for some WASM data structures.
     32 struct ModuleEnv;
     33 struct WasmFunction;
     34 class ErrorThrower;
     35 struct DecodeStruct;
     36 
     37 // Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}.
     38 typedef compiler::Node TFNode;
     39 typedef compiler::JSGraph TFGraph;
     40 }  // namespace wasm
     41 
     42 namespace compiler {
     43 class WasmCompilationUnit final {
     44  public:
     45   WasmCompilationUnit(wasm::ErrorThrower* thrower, Isolate* isolate,
     46                       wasm::ModuleEnv* module_env,
     47                       const wasm::WasmFunction* function, uint32_t index);
     48 
     49   Zone* graph_zone() { return graph_zone_.get(); }
     50   int index() const { return index_; }
     51 
     52   void ExecuteCompilation();
     53   Handle<Code> FinishCompilation();
     54 
     55   static Handle<Code> CompileWasmFunction(wasm::ErrorThrower* thrower,
     56                                           Isolate* isolate,
     57                                           wasm::ModuleEnv* module_env,
     58                                           const wasm::WasmFunction* function) {
     59     WasmCompilationUnit unit(thrower, isolate, module_env, function, 0);
     60     unit.ExecuteCompilation();
     61     return unit.FinishCompilation();
     62   }
     63 
     64  private:
     65   SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms);
     66 
     67   wasm::ErrorThrower* thrower_;
     68   Isolate* isolate_;
     69   wasm::ModuleEnv* module_env_;
     70   const wasm::WasmFunction* function_;
     71   // The graph zone is deallocated at the end of ExecuteCompilation.
     72   std::unique_ptr<Zone> graph_zone_;
     73   JSGraph* jsgraph_;
     74   Zone compilation_zone_;
     75   CompilationInfo info_;
     76   std::unique_ptr<CompilationJob> job_;
     77   uint32_t index_;
     78   wasm::Result<wasm::DecodeStruct*> graph_construction_result_;
     79   bool ok_;
     80 
     81   DISALLOW_COPY_AND_ASSIGN(WasmCompilationUnit);
     82 };
     83 
     84 // Wraps a JS function, producing a code object that can be called from WASM.
     85 Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
     86                                     wasm::FunctionSig* sig, uint32_t index,
     87                                     Handle<String> module_name,
     88                                     MaybeHandle<String> import_name);
     89 
     90 // Wraps a given wasm code object, producing a code object.
     91 Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::ModuleEnv* module,
     92                                     Handle<Code> wasm_code, uint32_t index);
     93 
     94 // Abstracts details of building TurboFan graph nodes for WASM to separate
     95 // the WASM decoder from the internal details of TurboFan.
     96 class WasmTrapHelper;
     97 typedef ZoneVector<Node*> NodeVector;
     98 class WasmGraphBuilder {
     99  public:
    100   WasmGraphBuilder(
    101       Zone* z, JSGraph* g, wasm::FunctionSig* function_signature,
    102       compiler::SourcePositionTable* source_position_table = nullptr);
    103 
    104   Node** Buffer(size_t count) {
    105     if (count > cur_bufsize_) {
    106       size_t new_size = count + cur_bufsize_ + 5;
    107       cur_buffer_ =
    108           reinterpret_cast<Node**>(zone_->New(new_size * sizeof(Node*)));
    109       cur_bufsize_ = new_size;
    110     }
    111     return cur_buffer_;
    112   }
    113 
    114   //-----------------------------------------------------------------------
    115   // Operations independent of {control} or {effect}.
    116   //-----------------------------------------------------------------------
    117   Node* Error();
    118   Node* Start(unsigned params);
    119   Node* Param(unsigned index, wasm::LocalType type);
    120   Node* Loop(Node* entry);
    121   Node* Terminate(Node* effect, Node* control);
    122   Node* Merge(unsigned count, Node** controls);
    123   Node* Phi(wasm::LocalType type, unsigned count, Node** vals, Node* control);
    124   Node* EffectPhi(unsigned count, Node** effects, Node* control);
    125   Node* NumberConstant(int32_t value);
    126   Node* Uint32Constant(uint32_t value);
    127   Node* Int32Constant(int32_t value);
    128   Node* Int64Constant(int64_t value);
    129   Node* Float32Constant(float value);
    130   Node* Float64Constant(double value);
    131   Node* HeapConstant(Handle<HeapObject> value);
    132   Node* Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
    133               wasm::WasmCodePosition position = wasm::kNoCodePosition);
    134   Node* Unop(wasm::WasmOpcode opcode, Node* input,
    135              wasm::WasmCodePosition position = wasm::kNoCodePosition);
    136   Node* GrowMemory(Node* input);
    137   Node* Throw(Node* input);
    138   Node* Catch(Node* input, wasm::WasmCodePosition position);
    139   unsigned InputCount(Node* node);
    140   bool IsPhiWithMerge(Node* phi, Node* merge);
    141   bool ThrowsException(Node* node, Node** if_success, Node** if_exception);
    142   void AppendToMerge(Node* merge, Node* from);
    143   void AppendToPhi(Node* phi, Node* from);
    144 
    145   void StackCheck(wasm::WasmCodePosition position, Node** effect = nullptr,
    146                   Node** control = nullptr);
    147 
    148   //-----------------------------------------------------------------------
    149   // Operations that read and/or write {control} and {effect}.
    150   //-----------------------------------------------------------------------
    151   Node* BranchNoHint(Node* cond, Node** true_node, Node** false_node);
    152   Node* BranchExpectTrue(Node* cond, Node** true_node, Node** false_node);
    153   Node* BranchExpectFalse(Node* cond, Node** true_node, Node** false_node);
    154 
    155   Node* Switch(unsigned count, Node* key);
    156   Node* IfValue(int32_t value, Node* sw);
    157   Node* IfDefault(Node* sw);
    158   Node* Return(unsigned count, Node** vals);
    159   Node* ReturnVoid();
    160   Node* Unreachable(wasm::WasmCodePosition position);
    161 
    162   Node* CallDirect(uint32_t index, Node** args, Node*** rets,
    163                    wasm::WasmCodePosition position);
    164   Node* CallIndirect(uint32_t index, Node** args, Node*** rets,
    165                      wasm::WasmCodePosition position);
    166 
    167   void BuildJSToWasmWrapper(Handle<Code> wasm_code, wasm::FunctionSig* sig);
    168   void BuildWasmToJSWrapper(Handle<JSReceiver> target, wasm::FunctionSig* sig);
    169 
    170   Node* ToJS(Node* node, wasm::LocalType type);
    171   Node* FromJS(Node* node, Node* context, wasm::LocalType type);
    172   Node* Invert(Node* node);
    173   void EnsureFunctionTableNodes();
    174 
    175   //-----------------------------------------------------------------------
    176   // Operations that concern the linear memory.
    177   //-----------------------------------------------------------------------
    178   Node* CurrentMemoryPages();
    179   Node* GetGlobal(uint32_t index);
    180   Node* SetGlobal(uint32_t index, Node* val);
    181   Node* LoadMem(wasm::LocalType type, MachineType memtype, Node* index,
    182                 uint32_t offset, uint32_t alignment,
    183                 wasm::WasmCodePosition position);
    184   Node* StoreMem(MachineType type, Node* index, uint32_t offset,
    185                  uint32_t alignment, Node* val,
    186                  wasm::WasmCodePosition position);
    187 
    188   static void PrintDebugName(Node* node);
    189 
    190   Node* Control() { return *control_; }
    191   Node* Effect() { return *effect_; }
    192 
    193   void set_module(wasm::ModuleEnv* module) { this->module_ = module; }
    194 
    195   void set_control_ptr(Node** control) { this->control_ = control; }
    196 
    197   void set_effect_ptr(Node** effect) { this->effect_ = effect; }
    198 
    199   wasm::FunctionSig* GetFunctionSignature() { return function_signature_; }
    200 
    201   void Int64LoweringForTesting();
    202 
    203   void SimdScalarLoweringForTesting();
    204 
    205   void SetSourcePosition(Node* node, wasm::WasmCodePosition position);
    206 
    207   Node* CreateS128Value(int32_t value);
    208 
    209   Node* SimdOp(wasm::WasmOpcode opcode, const NodeVector& inputs);
    210   Node* SimdExtractLane(wasm::WasmOpcode opcode, uint8_t lane, Node* input);
    211 
    212  private:
    213   static const int kDefaultBufferSize = 16;
    214   friend class WasmTrapHelper;
    215 
    216   Zone* zone_;
    217   JSGraph* jsgraph_;
    218   wasm::ModuleEnv* module_;
    219   Node* mem_buffer_;
    220   Node* mem_size_;
    221   NodeVector function_tables_;
    222   NodeVector function_table_sizes_;
    223   Node** control_;
    224   Node** effect_;
    225   Node** cur_buffer_;
    226   size_t cur_bufsize_;
    227   Node* def_buffer_[kDefaultBufferSize];
    228 
    229   WasmTrapHelper* trap_;
    230   wasm::FunctionSig* function_signature_;
    231   SetOncePointer<const Operator> allocate_heap_number_operator_;
    232 
    233   compiler::SourcePositionTable* source_position_table_ = nullptr;
    234 
    235   // Internal helper methods.
    236   JSGraph* jsgraph() { return jsgraph_; }
    237   Graph* graph();
    238 
    239   Node* String(const char* string);
    240   Node* MemSize(uint32_t offset);
    241   Node* MemBuffer(uint32_t offset);
    242   void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset,
    243                       wasm::WasmCodePosition position);
    244 
    245   Node* BuildChangeEndianness(Node* node, MachineType type,
    246                               wasm::LocalType wasmtype = wasm::kAstStmt);
    247 
    248   Node* MaskShiftCount32(Node* node);
    249   Node* MaskShiftCount64(Node* node);
    250 
    251   Node* BuildCCall(MachineSignature* sig, Node** args);
    252   Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args, Node*** rets,
    253                       wasm::WasmCodePosition position);
    254 
    255   Node* BuildF32CopySign(Node* left, Node* right);
    256   Node* BuildF64CopySign(Node* left, Node* right);
    257   Node* BuildI32SConvertF32(Node* input, wasm::WasmCodePosition position);
    258   Node* BuildI32SConvertF64(Node* input, wasm::WasmCodePosition position);
    259   Node* BuildI32UConvertF32(Node* input, wasm::WasmCodePosition position);
    260   Node* BuildI32UConvertF64(Node* input, wasm::WasmCodePosition position);
    261   Node* BuildI32Ctz(Node* input);
    262   Node* BuildI32Popcnt(Node* input);
    263   Node* BuildI64Ctz(Node* input);
    264   Node* BuildI64Popcnt(Node* input);
    265   Node* BuildBitCountingCall(Node* input, ExternalReference ref,
    266                              MachineRepresentation input_type);
    267 
    268   Node* BuildCFuncInstruction(ExternalReference ref, MachineType type,
    269                               Node* input0, Node* input1 = nullptr);
    270   Node* BuildF32Trunc(Node* input);
    271   Node* BuildF32Floor(Node* input);
    272   Node* BuildF32Ceil(Node* input);
    273   Node* BuildF32NearestInt(Node* input);
    274   Node* BuildF64Trunc(Node* input);
    275   Node* BuildF64Floor(Node* input);
    276   Node* BuildF64Ceil(Node* input);
    277   Node* BuildF64NearestInt(Node* input);
    278   Node* BuildI32Rol(Node* left, Node* right);
    279   Node* BuildI64Rol(Node* left, Node* right);
    280 
    281   Node* BuildF64Acos(Node* input);
    282   Node* BuildF64Asin(Node* input);
    283   Node* BuildF64Pow(Node* left, Node* right);
    284   Node* BuildF64Mod(Node* left, Node* right);
    285 
    286   Node* BuildIntToFloatConversionInstruction(
    287       Node* input, ExternalReference ref,
    288       MachineRepresentation parameter_representation,
    289       const MachineType result_type);
    290   Node* BuildF32SConvertI64(Node* input);
    291   Node* BuildF32UConvertI64(Node* input);
    292   Node* BuildF64SConvertI64(Node* input);
    293   Node* BuildF64UConvertI64(Node* input);
    294 
    295   Node* BuildFloatToIntConversionInstruction(
    296       Node* input, ExternalReference ref,
    297       MachineRepresentation parameter_representation,
    298       const MachineType result_type, wasm::WasmCodePosition position);
    299   Node* BuildI64SConvertF32(Node* input, wasm::WasmCodePosition position);
    300   Node* BuildI64UConvertF32(Node* input, wasm::WasmCodePosition position);
    301   Node* BuildI64SConvertF64(Node* input, wasm::WasmCodePosition position);
    302   Node* BuildI64UConvertF64(Node* input, wasm::WasmCodePosition position);
    303 
    304   Node* BuildI32DivS(Node* left, Node* right, wasm::WasmCodePosition position);
    305   Node* BuildI32RemS(Node* left, Node* right, wasm::WasmCodePosition position);
    306   Node* BuildI32DivU(Node* left, Node* right, wasm::WasmCodePosition position);
    307   Node* BuildI32RemU(Node* left, Node* right, wasm::WasmCodePosition position);
    308 
    309   Node* BuildI64DivS(Node* left, Node* right, wasm::WasmCodePosition position);
    310   Node* BuildI64RemS(Node* left, Node* right, wasm::WasmCodePosition position);
    311   Node* BuildI64DivU(Node* left, Node* right, wasm::WasmCodePosition position);
    312   Node* BuildI64RemU(Node* left, Node* right, wasm::WasmCodePosition position);
    313   Node* BuildDiv64Call(Node* left, Node* right, ExternalReference ref,
    314                        MachineType result_type, int trap_zero,
    315                        wasm::WasmCodePosition position);
    316 
    317   Node* BuildJavaScriptToNumber(Node* node, Node* context, Node* effect,
    318                                 Node* control);
    319 
    320   Node* BuildChangeInt32ToTagged(Node* value);
    321   Node* BuildChangeFloat64ToTagged(Node* value);
    322   Node* BuildChangeTaggedToFloat64(Node* value);
    323 
    324   Node* BuildChangeInt32ToSmi(Node* value);
    325   Node* BuildChangeSmiToInt32(Node* value);
    326   Node* BuildChangeUint32ToSmi(Node* value);
    327   Node* BuildChangeSmiToFloat64(Node* value);
    328   Node* BuildTestNotSmi(Node* value);
    329   Node* BuildSmiShiftBitsConstant();
    330 
    331   Node* BuildAllocateHeapNumberWithValue(Node* value, Node* control);
    332   Node* BuildLoadHeapNumberValue(Node* value, Node* control);
    333   Node* BuildHeapNumberValueIndexConstant();
    334 
    335   // Asm.js specific functionality.
    336   Node* BuildI32AsmjsSConvertF32(Node* input);
    337   Node* BuildI32AsmjsSConvertF64(Node* input);
    338   Node* BuildI32AsmjsUConvertF32(Node* input);
    339   Node* BuildI32AsmjsUConvertF64(Node* input);
    340   Node* BuildI32AsmjsDivS(Node* left, Node* right);
    341   Node* BuildI32AsmjsRemS(Node* left, Node* right);
    342   Node* BuildI32AsmjsDivU(Node* left, Node* right);
    343   Node* BuildI32AsmjsRemU(Node* left, Node* right);
    344   Node* BuildAsmjsLoadMem(MachineType type, Node* index);
    345   Node* BuildAsmjsStoreMem(MachineType type, Node* index, Node* val);
    346 
    347   Node** Realloc(Node** buffer, size_t old_count, size_t new_count) {
    348     Node** buf = Buffer(new_count);
    349     if (buf != buffer) memcpy(buf, buffer, old_count * sizeof(Node*));
    350     return buf;
    351   }
    352 
    353   int AddParameterNodes(Node** args, int pos, int param_count,
    354                         wasm::FunctionSig* sig);
    355 };
    356 }  // namespace compiler
    357 }  // namespace internal
    358 }  // namespace v8
    359 
    360 #endif  // V8_COMPILER_WASM_COMPILER_H_
    361