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 // Clients of this interface shouldn't depend on lots of compiler internals.
9 // Do not include anything from src/compiler here!
10 #include "src/wasm/wasm-opcodes.h"
11 #include "src/zone.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 namespace compiler {
17 // Forward declarations for some compiler data structures.
18 class Node;
19 class JSGraph;
20 class Graph;
21 }
22 
23 namespace wasm {
24 // Forward declarations for some WASM data structures.
25 struct ModuleEnv;
26 struct WasmFunction;
27 class ErrorThrower;
28 
29 // Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}.
30 typedef compiler::Node TFNode;
31 typedef compiler::JSGraph TFGraph;
32 }
33 
34 namespace compiler {
35 // Compiles a single function, producing a code object.
36 Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
37                                  wasm::ModuleEnv* module_env,
38                                  const wasm::WasmFunction& function, int index);
39 
40 // Wraps a JS function, producing a code object that can be called from WASM.
41 Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
42                                     Handle<JSFunction> function,
43                                     uint32_t index);
44 
45 // Wraps a given wasm code object, producing a JSFunction that can be called
46 // from JavaScript.
47 Handle<JSFunction> CompileJSToWasmWrapper(
48     Isolate* isolate, wasm::ModuleEnv* module, Handle<String> name,
49     Handle<Code> wasm_code, Handle<JSObject> module_object, uint32_t index);
50 
51 // Abstracts details of building TurboFan graph nodes for WASM to separate
52 // the WASM decoder from the internal details of TurboFan.
53 class WasmTrapHelper;
54 class WasmGraphBuilder {
55  public:
56   WasmGraphBuilder(Zone* z, JSGraph* g, wasm::FunctionSig* function_signature);
57 
Buffer(size_t count)58   Node** Buffer(size_t count) {
59     if (count > cur_bufsize_) {
60       size_t new_size = count + cur_bufsize_ + 5;
61       cur_buffer_ =
62           reinterpret_cast<Node**>(zone_->New(new_size * sizeof(Node*)));
63       cur_bufsize_ = new_size;
64     }
65     return cur_buffer_;
66   }
67 
68   //-----------------------------------------------------------------------
69   // Operations independent of {control} or {effect}.
70   //-----------------------------------------------------------------------
71   Node* Error();
72   Node* Start(unsigned params);
73   Node* Param(unsigned index, wasm::LocalType type);
74   Node* Loop(Node* entry);
75   Node* Terminate(Node* effect, Node* control);
76   Node* Merge(unsigned count, Node** controls);
77   Node* Phi(wasm::LocalType type, unsigned count, Node** vals, Node* control);
78   Node* EffectPhi(unsigned count, Node** effects, Node* control);
79   Node* Int32Constant(int32_t value);
80   Node* Int64Constant(int64_t value);
81   Node* Float32Constant(float value);
82   Node* Float64Constant(double value);
83   Node* Constant(Handle<Object> value);
84   Node* Binop(wasm::WasmOpcode opcode, Node* left, Node* right);
85   Node* Unop(wasm::WasmOpcode opcode, Node* input);
86   unsigned InputCount(Node* node);
87   bool IsPhiWithMerge(Node* phi, Node* merge);
88   void AppendToMerge(Node* merge, Node* from);
89   void AppendToPhi(Node* merge, Node* phi, Node* from);
90 
91   //-----------------------------------------------------------------------
92   // Operations that read and/or write {control} and {effect}.
93   //-----------------------------------------------------------------------
94   Node* Branch(Node* cond, Node** true_node, Node** false_node);
95   Node* Switch(unsigned count, Node* key);
96   Node* IfValue(int32_t value, Node* sw);
97   Node* IfDefault(Node* sw);
98   Node* Return(unsigned count, Node** vals);
99   Node* ReturnVoid();
100   Node* Unreachable();
101 
102   Node* CallDirect(uint32_t index, Node** args);
103   Node* CallIndirect(uint32_t index, Node** args);
104   void BuildJSToWasmWrapper(Handle<Code> wasm_code, wasm::FunctionSig* sig);
105   void BuildWasmToJSWrapper(Handle<JSFunction> function,
106                             wasm::FunctionSig* sig);
107   Node* ToJS(Node* node, Node* context, wasm::LocalType type);
108   Node* FromJS(Node* node, Node* context, wasm::LocalType type);
109   Node* Invert(Node* node);
110   Node* FunctionTable();
111 
112   //-----------------------------------------------------------------------
113   // Operations that concern the linear memory.
114   //-----------------------------------------------------------------------
115   Node* MemSize(uint32_t offset);
116   Node* LoadGlobal(uint32_t index);
117   Node* StoreGlobal(uint32_t index, Node* val);
118   Node* LoadMem(wasm::LocalType type, MachineType memtype, Node* index,
119                 uint32_t offset);
120   Node* StoreMem(MachineType type, Node* index, uint32_t offset, Node* val);
121 
122   static void PrintDebugName(Node* node);
123 
Control()124   Node* Control() { return *control_; }
Effect()125   Node* Effect() { return *effect_; }
126 
set_module(wasm::ModuleEnv * module)127   void set_module(wasm::ModuleEnv* module) { this->module_ = module; }
128 
set_control_ptr(Node ** control)129   void set_control_ptr(Node** control) { this->control_ = control; }
130 
set_effect_ptr(Node ** effect)131   void set_effect_ptr(Node** effect) { this->effect_ = effect; }
132 
GetFunctionSignature()133   wasm::FunctionSig* GetFunctionSignature() { return function_signature_; }
134 
135  private:
136   static const int kDefaultBufferSize = 16;
137   friend class WasmTrapHelper;
138 
139   Zone* zone_;
140   JSGraph* jsgraph_;
141   wasm::ModuleEnv* module_;
142   Node* mem_buffer_;
143   Node* mem_size_;
144   Node* function_table_;
145   Node** control_;
146   Node** effect_;
147   Node** cur_buffer_;
148   size_t cur_bufsize_;
149   Node* def_buffer_[kDefaultBufferSize];
150 
151   WasmTrapHelper* trap_;
152   wasm::FunctionSig* function_signature_;
153 
154   // Internal helper methods.
jsgraph()155   JSGraph* jsgraph() { return jsgraph_; }
156   Graph* graph();
157 
158   Node* String(const char* string);
159   Node* MemBuffer(uint32_t offset);
160   void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset);
161 
162   Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args);
163   Node* BuildF32Neg(Node* input);
164   Node* BuildF64Neg(Node* input);
165   Node* BuildF32CopySign(Node* left, Node* right);
166   Node* BuildF64CopySign(Node* left, Node* right);
167   Node* BuildF32Min(Node* left, Node* right);
168   Node* BuildF32Max(Node* left, Node* right);
169   Node* BuildF64Min(Node* left, Node* right);
170   Node* BuildF64Max(Node* left, Node* right);
171   Node* BuildI32SConvertF32(Node* input);
172   Node* BuildI32SConvertF64(Node* input);
173   Node* BuildI32UConvertF32(Node* input);
174   Node* BuildI32UConvertF64(Node* input);
175   Node* BuildI32Ctz(Node* input);
176   Node* BuildI32Popcnt(Node* input);
177   Node* BuildI64Ctz(Node* input);
178   Node* BuildI64Popcnt(Node* input);
179 
Realloc(Node ** buffer,size_t count)180   Node** Realloc(Node** buffer, size_t count) {
181     Node** buf = Buffer(count);
182     if (buf != buffer) memcpy(buf, buffer, count * sizeof(Node*));
183     return buf;
184   }
185 };
186 }  // namespace compiler
187 }  // namespace internal
188 }  // namespace v8
189 
190 #endif  // V8_COMPILER_WASM_COMPILER_H_
191