blob: c03de3d7d46eef4b1c367737b655a4deedd78599 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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!
Ben Murdoch61f157c2016-09-16 13:49:30 +010010#include "src/compiler.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/wasm/wasm-opcodes.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010012#include "src/wasm/wasm-result.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013#include "src/zone.h"
14
15namespace v8 {
16namespace internal {
17
18namespace compiler {
19// Forward declarations for some compiler data structures.
20class Node;
21class JSGraph;
22class Graph;
Ben Murdochc5610432016-08-08 18:44:38 +010023class Operator;
24class SourcePositionTable;
Ben Murdoch61f157c2016-09-16 13:49:30 +010025} // namespace compiler
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000026
27namespace wasm {
28// Forward declarations for some WASM data structures.
29struct ModuleEnv;
30struct WasmFunction;
31class ErrorThrower;
Ben Murdoch61f157c2016-09-16 13:49:30 +010032struct Tree;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033
34// Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}.
35typedef compiler::Node TFNode;
36typedef compiler::JSGraph TFGraph;
Ben Murdoch61f157c2016-09-16 13:49:30 +010037} // namespace wasm
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000038
39namespace compiler {
Ben Murdoch61f157c2016-09-16 13:49:30 +010040class WasmCompilationUnit final {
41 public:
42 WasmCompilationUnit(wasm::ErrorThrower* thrower, Isolate* isolate,
43 wasm::ModuleEnv* module_env,
44 const wasm::WasmFunction* function, uint32_t index);
45
46 Zone* graph_zone() { return graph_zone_.get(); }
47 int index() const { return index_; }
48
49 void ExecuteCompilation();
50 Handle<Code> FinishCompilation();
51
52 static Handle<Code> CompileWasmFunction(wasm::ErrorThrower* thrower,
53 Isolate* isolate,
54 wasm::ModuleEnv* module_env,
55 const wasm::WasmFunction* function) {
56 WasmCompilationUnit unit(thrower, isolate, module_env, function, 0);
57 unit.ExecuteCompilation();
58 return unit.FinishCompilation();
59 }
60
61 private:
62 SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms);
63
64 wasm::ErrorThrower* thrower_;
65 Isolate* isolate_;
66 wasm::ModuleEnv* module_env_;
67 const wasm::WasmFunction* function_;
68 // The graph zone is deallocated at the end of ExecuteCompilation.
69 base::SmartPointer<Zone> graph_zone_;
70 JSGraph* jsgraph_;
71 Zone compilation_zone_;
72 CompilationInfo info_;
73 base::SmartPointer<CompilationJob> job_;
74 uint32_t index_;
75 wasm::Result<wasm::Tree*> graph_construction_result_;
76 bool ok_;
77};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078
79// Wraps a JS function, producing a code object that can be called from WASM.
Ben Murdoch61f157c2016-09-16 13:49:30 +010080Handle<Code> CompileWasmToJSWrapper(Isolate* isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 Handle<JSFunction> function,
Ben Murdochda12d292016-06-02 14:46:10 +010082 wasm::FunctionSig* sig,
83 wasm::WasmName module_name,
84 wasm::WasmName function_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000085
86// Wraps a given wasm code object, producing a JSFunction that can be called
87// from JavaScript.
88Handle<JSFunction> CompileJSToWasmWrapper(
89 Isolate* isolate, wasm::ModuleEnv* module, Handle<String> name,
90 Handle<Code> wasm_code, Handle<JSObject> module_object, uint32_t index);
91
92// Abstracts details of building TurboFan graph nodes for WASM to separate
93// the WASM decoder from the internal details of TurboFan.
94class WasmTrapHelper;
95class WasmGraphBuilder {
96 public:
Ben Murdochc5610432016-08-08 18:44:38 +010097 WasmGraphBuilder(
98 Zone* z, JSGraph* g, wasm::FunctionSig* function_signature,
99 compiler::SourcePositionTable* source_position_table = nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000100
101 Node** Buffer(size_t count) {
102 if (count > cur_bufsize_) {
103 size_t new_size = count + cur_bufsize_ + 5;
104 cur_buffer_ =
105 reinterpret_cast<Node**>(zone_->New(new_size * sizeof(Node*)));
106 cur_bufsize_ = new_size;
107 }
108 return cur_buffer_;
109 }
110
111 //-----------------------------------------------------------------------
112 // Operations independent of {control} or {effect}.
113 //-----------------------------------------------------------------------
114 Node* Error();
115 Node* Start(unsigned params);
116 Node* Param(unsigned index, wasm::LocalType type);
117 Node* Loop(Node* entry);
118 Node* Terminate(Node* effect, Node* control);
119 Node* Merge(unsigned count, Node** controls);
120 Node* Phi(wasm::LocalType type, unsigned count, Node** vals, Node* control);
121 Node* EffectPhi(unsigned count, Node** effects, Node* control);
Ben Murdochc5610432016-08-08 18:44:38 +0100122 Node* NumberConstant(int32_t value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123 Node* Int32Constant(int32_t value);
124 Node* Int64Constant(int64_t value);
125 Node* Float32Constant(float value);
126 Node* Float64Constant(double value);
Ben Murdochc5610432016-08-08 18:44:38 +0100127 Node* HeapConstant(Handle<HeapObject> value);
128 Node* Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
129 wasm::WasmCodePosition position = wasm::kNoCodePosition);
130 Node* Unop(wasm::WasmOpcode opcode, Node* input,
131 wasm::WasmCodePosition position = wasm::kNoCodePosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132 unsigned InputCount(Node* node);
133 bool IsPhiWithMerge(Node* phi, Node* merge);
134 void AppendToMerge(Node* merge, Node* from);
Ben Murdochc5610432016-08-08 18:44:38 +0100135 void AppendToPhi(Node* phi, Node* from);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000136
137 //-----------------------------------------------------------------------
138 // Operations that read and/or write {control} and {effect}.
139 //-----------------------------------------------------------------------
140 Node* Branch(Node* cond, Node** true_node, Node** false_node);
141 Node* Switch(unsigned count, Node* key);
142 Node* IfValue(int32_t value, Node* sw);
143 Node* IfDefault(Node* sw);
144 Node* Return(unsigned count, Node** vals);
145 Node* ReturnVoid();
Ben Murdochc5610432016-08-08 18:44:38 +0100146 Node* Unreachable(wasm::WasmCodePosition position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147
Ben Murdochc5610432016-08-08 18:44:38 +0100148 Node* CallDirect(uint32_t index, Node** args,
149 wasm::WasmCodePosition position);
150 Node* CallImport(uint32_t index, Node** args,
151 wasm::WasmCodePosition position);
152 Node* CallIndirect(uint32_t index, Node** args,
153 wasm::WasmCodePosition position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154 void BuildJSToWasmWrapper(Handle<Code> wasm_code, wasm::FunctionSig* sig);
155 void BuildWasmToJSWrapper(Handle<JSFunction> function,
156 wasm::FunctionSig* sig);
Ben Murdochc5610432016-08-08 18:44:38 +0100157
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000158 Node* ToJS(Node* node, Node* context, wasm::LocalType type);
159 Node* FromJS(Node* node, Node* context, wasm::LocalType type);
160 Node* Invert(Node* node);
161 Node* FunctionTable();
162
163 //-----------------------------------------------------------------------
164 // Operations that concern the linear memory.
165 //-----------------------------------------------------------------------
166 Node* MemSize(uint32_t offset);
167 Node* LoadGlobal(uint32_t index);
168 Node* StoreGlobal(uint32_t index, Node* val);
169 Node* LoadMem(wasm::LocalType type, MachineType memtype, Node* index,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100170 uint32_t offset, uint32_t alignment,
171 wasm::WasmCodePosition position);
172 Node* StoreMem(MachineType type, Node* index, uint32_t offset,
173 uint32_t alignment, Node* val,
Ben Murdochc5610432016-08-08 18:44:38 +0100174 wasm::WasmCodePosition position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175
176 static void PrintDebugName(Node* node);
177
178 Node* Control() { return *control_; }
179 Node* Effect() { return *effect_; }
180
181 void set_module(wasm::ModuleEnv* module) { this->module_ = module; }
182
183 void set_control_ptr(Node** control) { this->control_ = control; }
184
185 void set_effect_ptr(Node** effect) { this->effect_ = effect; }
186
187 wasm::FunctionSig* GetFunctionSignature() { return function_signature_; }
188
Ben Murdoch097c5b22016-05-18 11:27:45 +0100189 void Int64LoweringForTesting();
190
Ben Murdochc5610432016-08-08 18:44:38 +0100191 void SetSourcePosition(Node* node, wasm::WasmCodePosition position);
192
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 private:
194 static const int kDefaultBufferSize = 16;
195 friend class WasmTrapHelper;
196
197 Zone* zone_;
198 JSGraph* jsgraph_;
199 wasm::ModuleEnv* module_;
200 Node* mem_buffer_;
201 Node* mem_size_;
202 Node* function_table_;
203 Node** control_;
204 Node** effect_;
205 Node** cur_buffer_;
206 size_t cur_bufsize_;
207 Node* def_buffer_[kDefaultBufferSize];
208
209 WasmTrapHelper* trap_;
210 wasm::FunctionSig* function_signature_;
Ben Murdochc5610432016-08-08 18:44:38 +0100211 SetOncePointer<const Operator> allocate_heap_number_operator_;
212
213 compiler::SourcePositionTable* source_position_table_ = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214
215 // Internal helper methods.
216 JSGraph* jsgraph() { return jsgraph_; }
217 Graph* graph();
218
219 Node* String(const char* string);
220 Node* MemBuffer(uint32_t offset);
Ben Murdochc5610432016-08-08 18:44:38 +0100221 void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset,
222 wasm::WasmCodePosition position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223
Ben Murdoch61f157c2016-09-16 13:49:30 +0100224 MachineType GetTypeForUnalignedAccess(uint32_t alignment,
225 bool signExtend = false);
226
227 Node* GetUnalignedLoadOffsetNode(Node* baseOffset, int numberOfBytes,
228 int stride, int current);
229
230 Node* BuildUnalignedLoad(wasm::LocalType type, MachineType memtype,
231 Node* index, uint32_t offset, uint32_t alignment);
232 Node* GetUnalignedStoreOffsetNode(Node* baseOffset, int numberOfBytes,
233 int stride, int current);
234 Node* BuildUnalignedStore(MachineType memtype, Node* index, uint32_t offset,
235 uint32_t alignment, Node* val);
236
Ben Murdochda12d292016-06-02 14:46:10 +0100237 Node* MaskShiftCount32(Node* node);
238 Node* MaskShiftCount64(Node* node);
239
Ben Murdoch097c5b22016-05-18 11:27:45 +0100240 Node* BuildCCall(MachineSignature* sig, Node** args);
Ben Murdochc5610432016-08-08 18:44:38 +0100241 Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args,
242 wasm::WasmCodePosition position);
Ben Murdochda12d292016-06-02 14:46:10 +0100243
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 Node* BuildF32Neg(Node* input);
245 Node* BuildF64Neg(Node* input);
246 Node* BuildF32CopySign(Node* left, Node* right);
247 Node* BuildF64CopySign(Node* left, Node* right);
248 Node* BuildF32Min(Node* left, Node* right);
249 Node* BuildF32Max(Node* left, Node* right);
250 Node* BuildF64Min(Node* left, Node* right);
251 Node* BuildF64Max(Node* left, Node* right);
Ben Murdochc5610432016-08-08 18:44:38 +0100252 Node* BuildI32SConvertF32(Node* input, wasm::WasmCodePosition position);
253 Node* BuildI32SConvertF64(Node* input, wasm::WasmCodePosition position);
254 Node* BuildI32UConvertF32(Node* input, wasm::WasmCodePosition position);
255 Node* BuildI32UConvertF64(Node* input, wasm::WasmCodePosition position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000256 Node* BuildI32Ctz(Node* input);
257 Node* BuildI32Popcnt(Node* input);
258 Node* BuildI64Ctz(Node* input);
259 Node* BuildI64Popcnt(Node* input);
Ben Murdochc5610432016-08-08 18:44:38 +0100260 Node* BuildBitCountingCall(Node* input, ExternalReference ref,
261 MachineRepresentation input_type);
262
Ben Murdochda12d292016-06-02 14:46:10 +0100263 Node* BuildCFuncInstruction(ExternalReference ref, MachineType type,
264 Node* input0, Node* input1 = nullptr);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100265 Node* BuildF32Trunc(Node* input);
266 Node* BuildF32Floor(Node* input);
267 Node* BuildF32Ceil(Node* input);
268 Node* BuildF32NearestInt(Node* input);
269 Node* BuildF64Trunc(Node* input);
270 Node* BuildF64Floor(Node* input);
271 Node* BuildF64Ceil(Node* input);
272 Node* BuildF64NearestInt(Node* input);
Ben Murdochda12d292016-06-02 14:46:10 +0100273 Node* BuildI32Rol(Node* left, Node* right);
274 Node* BuildI64Rol(Node* left, Node* right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275
Ben Murdochda12d292016-06-02 14:46:10 +0100276 Node* BuildF64Acos(Node* input);
277 Node* BuildF64Asin(Node* input);
Ben Murdochda12d292016-06-02 14:46:10 +0100278 Node* BuildF64Pow(Node* left, Node* right);
Ben Murdochda12d292016-06-02 14:46:10 +0100279 Node* BuildF64Mod(Node* left, Node* right);
280
281 Node* BuildIntToFloatConversionInstruction(
282 Node* input, ExternalReference ref,
283 MachineRepresentation parameter_representation,
284 const MachineType result_type);
285 Node* BuildF32SConvertI64(Node* input);
286 Node* BuildF32UConvertI64(Node* input);
287 Node* BuildF64SConvertI64(Node* input);
288 Node* BuildF64UConvertI64(Node* input);
289
290 Node* BuildFloatToIntConversionInstruction(
291 Node* input, ExternalReference ref,
292 MachineRepresentation parameter_representation,
Ben Murdochc5610432016-08-08 18:44:38 +0100293 const MachineType result_type, wasm::WasmCodePosition position);
294 Node* BuildI64SConvertF32(Node* input, wasm::WasmCodePosition position);
295 Node* BuildI64UConvertF32(Node* input, wasm::WasmCodePosition position);
296 Node* BuildI64SConvertF64(Node* input, wasm::WasmCodePosition position);
297 Node* BuildI64UConvertF64(Node* input, wasm::WasmCodePosition position);
Ben Murdochda12d292016-06-02 14:46:10 +0100298
Ben Murdochc5610432016-08-08 18:44:38 +0100299 Node* BuildI32DivS(Node* left, Node* right, wasm::WasmCodePosition position);
300 Node* BuildI32RemS(Node* left, Node* right, wasm::WasmCodePosition position);
301 Node* BuildI32DivU(Node* left, Node* right, wasm::WasmCodePosition position);
302 Node* BuildI32RemU(Node* left, Node* right, wasm::WasmCodePosition position);
Ben Murdochda12d292016-06-02 14:46:10 +0100303
Ben Murdochc5610432016-08-08 18:44:38 +0100304 Node* BuildI64DivS(Node* left, Node* right, wasm::WasmCodePosition position);
305 Node* BuildI64RemS(Node* left, Node* right, wasm::WasmCodePosition position);
306 Node* BuildI64DivU(Node* left, Node* right, wasm::WasmCodePosition position);
307 Node* BuildI64RemU(Node* left, Node* right, wasm::WasmCodePosition position);
Ben Murdochda12d292016-06-02 14:46:10 +0100308 Node* BuildDiv64Call(Node* left, Node* right, ExternalReference ref,
Ben Murdochc5610432016-08-08 18:44:38 +0100309 MachineType result_type, int trap_zero,
310 wasm::WasmCodePosition position);
311
312 Node* BuildJavaScriptToNumber(Node* node, Node* context, Node* effect,
313 Node* control);
314 Node* BuildChangeInt32ToTagged(Node* value);
315 Node* BuildChangeFloat64ToTagged(Node* value);
316 Node* BuildChangeTaggedToFloat64(Node* value);
317
318 Node* BuildChangeInt32ToSmi(Node* value);
319 Node* BuildChangeSmiToInt32(Node* value);
320 Node* BuildChangeSmiToFloat64(Node* value);
321 Node* BuildTestNotSmi(Node* value);
322 Node* BuildSmiShiftBitsConstant();
323
324 Node* BuildAllocateHeapNumberWithValue(Node* value, Node* control);
325 Node* BuildLoadHeapNumberValue(Node* value, Node* control);
326 Node* BuildHeapNumberValueIndexConstant();
327
328 // Asm.js specific functionality.
329 Node* BuildI32AsmjsSConvertF32(Node* input);
330 Node* BuildI32AsmjsSConvertF64(Node* input);
331 Node* BuildI32AsmjsUConvertF32(Node* input);
332 Node* BuildI32AsmjsUConvertF64(Node* input);
333 Node* BuildI32AsmjsDivS(Node* left, Node* right);
334 Node* BuildI32AsmjsRemS(Node* left, Node* right);
335 Node* BuildI32AsmjsDivU(Node* left, Node* right);
336 Node* BuildI32AsmjsRemU(Node* left, Node* right);
337 Node* BuildAsmjsLoadMem(MachineType type, Node* index);
338 Node* BuildAsmjsStoreMem(MachineType type, Node* index, Node* val);
Ben Murdochda12d292016-06-02 14:46:10 +0100339
340 Node** Realloc(Node** buffer, size_t old_count, size_t new_count) {
341 Node** buf = Buffer(new_count);
342 if (buf != buffer) memcpy(buf, buffer, old_count * sizeof(Node*));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343 return buf;
344 }
345};
346} // namespace compiler
347} // namespace internal
348} // namespace v8
349
350#endif // V8_COMPILER_WASM_COMPILER_H_