Line data Source code
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/runtime/runtime.h"
13 : #include "src/wasm/function-body-decoder.h"
14 : #include "src/wasm/function-compiler.h"
15 : #include "src/wasm/wasm-module.h"
16 : #include "src/wasm/wasm-opcodes.h"
17 : #include "src/wasm/wasm-result.h"
18 : #include "src/zone/zone.h"
19 :
20 : namespace v8 {
21 : namespace internal {
22 : struct AssemblerOptions;
23 :
24 : namespace compiler {
25 : // Forward declarations for some compiler data structures.
26 : class CallDescriptor;
27 : class Graph;
28 : class MachineGraph;
29 : class Node;
30 : class NodeOriginTable;
31 : class Operator;
32 : class SourcePositionTable;
33 : class WasmDecorator;
34 : enum class TrapId : uint32_t;
35 : } // namespace compiler
36 :
37 : namespace wasm {
38 : struct DecodeStruct;
39 : // Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}.
40 : using TFNode = compiler::Node;
41 : using TFGraph = compiler::MachineGraph;
42 : class WasmCode;
43 : struct WasmFeatures;
44 : } // namespace wasm
45 :
46 : namespace compiler {
47 :
48 631300 : class TurbofanWasmCompilationUnit {
49 : public:
50 : explicit TurbofanWasmCompilationUnit(wasm::WasmCompilationUnit* wasm_unit);
51 : ~TurbofanWasmCompilationUnit();
52 :
53 : bool BuildGraphForWasmFunction(AccountingAllocator* allocator,
54 : wasm::CompilationEnv* env,
55 : const wasm::FunctionBody& func_body,
56 : wasm::WasmFeatures* detected,
57 : double* decode_ms, MachineGraph* mcgraph,
58 : NodeOriginTable* node_origins,
59 : SourcePositionTable* source_positions);
60 :
61 : wasm::WasmCompilationResult ExecuteCompilation(wasm::WasmEngine*,
62 : wasm::CompilationEnv*,
63 : const wasm::FunctionBody&,
64 : Counters*,
65 : wasm::WasmFeatures* detected);
66 :
67 : private:
68 : wasm::WasmCompilationUnit* const wasm_unit_;
69 :
70 : DISALLOW_COPY_AND_ASSIGN(TurbofanWasmCompilationUnit);
71 : };
72 :
73 : class InterpreterCompilationUnit final {
74 : public:
75 : explicit InterpreterCompilationUnit(wasm::WasmCompilationUnit* wasm_unit)
76 1439 : : wasm_unit_(wasm_unit) {}
77 :
78 : wasm::WasmCompilationResult ExecuteCompilation(wasm::WasmEngine*,
79 : wasm::CompilationEnv*,
80 : const wasm::FunctionBody&,
81 : Counters*,
82 : wasm::WasmFeatures* detected);
83 :
84 : private:
85 : wasm::WasmCompilationUnit* const wasm_unit_;
86 :
87 : DISALLOW_COPY_AND_ASSIGN(InterpreterCompilationUnit);
88 : };
89 :
90 : // Calls to WASM imports are handled in several different ways, depending on the
91 : // type of the target function/callable and whether the signature matches the
92 : // argument arity.
93 : enum class WasmImportCallKind : uint8_t {
94 : kLinkError, // static WASM->WASM type error
95 : kRuntimeTypeError, // runtime WASM->JS type error
96 : kWasmToWasm, // fast WASM->WASM call
97 : kJSFunctionArityMatch, // fast WASM->JS call
98 : kJSFunctionArityMatchSloppy, // fast WASM->JS call, sloppy receiver
99 : kJSFunctionArityMismatch, // WASM->JS, needs adapter frame
100 : kJSFunctionArityMismatchSloppy, // WASM->JS, needs adapter frame, sloppy
101 : // Math functions imported from JavaScript that are intrinsified
102 : kFirstMathIntrinsic,
103 : kF64Acos = kFirstMathIntrinsic,
104 : kF64Asin,
105 : kF64Atan,
106 : kF64Cos,
107 : kF64Sin,
108 : kF64Tan,
109 : kF64Exp,
110 : kF64Log,
111 : kF64Atan2,
112 : kF64Pow,
113 : kF64Ceil,
114 : kF64Floor,
115 : kF64Sqrt,
116 : kF64Min,
117 : kF64Max,
118 : kF64Abs,
119 : kF32Min,
120 : kF32Max,
121 : kF32Abs,
122 : kF32Ceil,
123 : kF32Floor,
124 : kF32Sqrt,
125 : kF32ConvertF64,
126 : kLastMathIntrinsic = kF32ConvertF64,
127 : // For everything else, there's the call builtin.
128 : kUseCallBuiltin
129 : };
130 :
131 : V8_EXPORT_PRIVATE WasmImportCallKind
132 : GetWasmImportCallKind(Handle<JSReceiver> callable, wasm::FunctionSig* sig,
133 : bool has_bigint_feature);
134 :
135 : // Compiles an import call wrapper, which allows WASM to call imports.
136 : V8_EXPORT_PRIVATE wasm::WasmCode* CompileWasmImportCallWrapper(
137 : wasm::WasmEngine*, wasm::NativeModule*, WasmImportCallKind,
138 : wasm::FunctionSig*, bool source_positions);
139 :
140 : // Creates a code object calling a wasm function with the given signature,
141 : // callable from JS.
142 : V8_EXPORT_PRIVATE MaybeHandle<Code> CompileJSToWasmWrapper(Isolate*,
143 : wasm::FunctionSig*,
144 : bool is_import);
145 :
146 : // Compiles a stub that redirects a call to a wasm function to the wasm
147 : // interpreter. It's ABI compatible with the compiled wasm function.
148 : V8_EXPORT_PRIVATE wasm::WasmCompilationResult CompileWasmInterpreterEntry(
149 : wasm::WasmEngine*, const wasm::WasmFeatures& enabled_features,
150 : uint32_t func_index, wasm::FunctionSig*);
151 :
152 : enum CWasmEntryParameters {
153 : kCodeEntry,
154 : kObjectRef,
155 : kArgumentsBuffer,
156 : // marker:
157 : kNumParameters
158 : };
159 :
160 : // Compiles a stub with JS linkage, taking parameters as described by
161 : // {CWasmEntryParameters}. It loads the wasm parameters from the argument
162 : // buffer and calls the wasm function given as first parameter.
163 : MaybeHandle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig);
164 :
165 : // Values from the instance object are cached between WASM-level function calls.
166 : // This struct allows the SSA environment handling this cache to be defined
167 : // and manipulated in wasm-compiler.{h,cc} instead of inside the WASM decoder.
168 : // (Note that currently, the globals base is immutable, so not cached here.)
169 : struct WasmInstanceCacheNodes {
170 : Node* mem_start;
171 : Node* mem_size;
172 : Node* mem_mask;
173 : };
174 :
175 : // Abstracts details of building TurboFan graph nodes for wasm to separate
176 : // the wasm decoder from the internal details of TurboFan.
177 : class WasmGraphBuilder {
178 : public:
179 : enum EnforceBoundsCheck : bool { // --
180 : kNeedsBoundsCheck = true,
181 : kCanOmitBoundsCheck = false
182 : };
183 : enum UseRetpoline : bool { // --
184 : kRetpoline = true,
185 : kNoRetpoline = false
186 : };
187 : enum ExtraCallableParam : bool { // --
188 : kExtraCallableParam = true,
189 : kNoExtraCallableParam = false
190 : };
191 :
192 : V8_EXPORT_PRIVATE WasmGraphBuilder(
193 : wasm::CompilationEnv* env, Zone* zone, MachineGraph* mcgraph,
194 : wasm::FunctionSig* sig, compiler::SourcePositionTable* spt = nullptr);
195 :
196 1918605 : Node** Buffer(size_t count) {
197 1918605 : if (count > cur_bufsize_) {
198 4836 : size_t new_size = count + cur_bufsize_ + 5;
199 : cur_buffer_ =
200 4836 : reinterpret_cast<Node**>(zone_->New(new_size * sizeof(Node*)));
201 4836 : cur_bufsize_ = new_size;
202 : }
203 1918605 : return cur_buffer_;
204 : }
205 :
206 : //-----------------------------------------------------------------------
207 : // Operations independent of {control} or {effect}.
208 : //-----------------------------------------------------------------------
209 : Node* Error();
210 : Node* Start(unsigned params);
211 : Node* Param(unsigned index);
212 : Node* Loop(Node* entry);
213 : Node* TerminateLoop(Node* effect, Node* control);
214 : Node* TerminateThrow(Node* effect, Node* control);
215 : Node* Merge(unsigned count, Node** controls);
216 : Node* Phi(wasm::ValueType type, unsigned count, Node** vals, Node* control);
217 : Node* CreateOrMergeIntoPhi(MachineRepresentation rep, Node* merge,
218 : Node* tnode, Node* fnode);
219 : Node* CreateOrMergeIntoEffectPhi(Node* merge, Node* tnode, Node* fnode);
220 : Node* EffectPhi(unsigned count, Node** effects, Node* control);
221 : Node* RefNull();
222 : Node* Uint32Constant(uint32_t value);
223 : Node* Int32Constant(int32_t value);
224 : Node* Int64Constant(int64_t value);
225 : Node* IntPtrConstant(intptr_t value);
226 : Node* Float32Constant(float value);
227 : Node* Float64Constant(double value);
228 : Node* Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
229 : wasm::WasmCodePosition position = wasm::kNoCodePosition);
230 : Node* Unop(wasm::WasmOpcode opcode, Node* input,
231 : wasm::WasmCodePosition position = wasm::kNoCodePosition);
232 : Node* MemoryGrow(Node* input);
233 : Node* Throw(uint32_t exception_index, const wasm::WasmException* exception,
234 : const Vector<Node*> values);
235 : Node* Rethrow(Node* except_obj);
236 : Node* ExceptionTagEqual(Node* caught_tag, Node* expected_tag);
237 : Node* LoadExceptionTagFromTable(uint32_t exception_index);
238 : Node* GetExceptionTag(Node* except_obj);
239 : Node** GetExceptionValues(Node* except_obj,
240 : const wasm::WasmException* exception);
241 : bool IsPhiWithMerge(Node* phi, Node* merge);
242 : bool ThrowsException(Node* node, Node** if_success, Node** if_exception);
243 : void AppendToMerge(Node* merge, Node* from);
244 : void AppendToPhi(Node* phi, Node* from);
245 :
246 : void StackCheck(wasm::WasmCodePosition position, Node** effect = nullptr,
247 : Node** control = nullptr);
248 :
249 : void PatchInStackCheckIfNeeded();
250 :
251 : //-----------------------------------------------------------------------
252 : // Operations that read and/or write {control} and {effect}.
253 : //-----------------------------------------------------------------------
254 : Node* BranchNoHint(Node* cond, Node** true_node, Node** false_node);
255 : Node* BranchExpectTrue(Node* cond, Node** true_node, Node** false_node);
256 : Node* BranchExpectFalse(Node* cond, Node** true_node, Node** false_node);
257 :
258 : Node* TrapIfTrue(wasm::TrapReason reason, Node* cond,
259 : wasm::WasmCodePosition position);
260 : Node* TrapIfFalse(wasm::TrapReason reason, Node* cond,
261 : wasm::WasmCodePosition position);
262 : Node* TrapIfEq32(wasm::TrapReason reason, Node* node, int32_t val,
263 : wasm::WasmCodePosition position);
264 : Node* ZeroCheck32(wasm::TrapReason reason, Node* node,
265 : wasm::WasmCodePosition position);
266 : Node* TrapIfEq64(wasm::TrapReason reason, Node* node, int64_t val,
267 : wasm::WasmCodePosition position);
268 : Node* ZeroCheck64(wasm::TrapReason reason, Node* node,
269 : wasm::WasmCodePosition position);
270 :
271 : Node* Switch(unsigned count, Node* key);
272 : Node* IfValue(int32_t value, Node* sw);
273 : Node* IfDefault(Node* sw);
274 : Node* Return(unsigned count, Node** nodes);
275 : template <typename... Nodes>
276 : Node* Return(Node* fst, Nodes*... more) {
277 151349 : Node* arr[] = {fst, more...};
278 151349 : return Return(arraysize(arr), arr);
279 : }
280 : Node* ReturnVoid();
281 : Node* Unreachable(wasm::WasmCodePosition position);
282 :
283 : Node* CallDirect(uint32_t index, Node** args, Node*** rets,
284 : wasm::WasmCodePosition position);
285 : Node* CallIndirect(uint32_t table_index, uint32_t sig_index, Node** args,
286 : Node*** rets, wasm::WasmCodePosition position);
287 :
288 : Node* ReturnCall(uint32_t index, Node** args,
289 : wasm::WasmCodePosition position);
290 : Node* ReturnCallIndirect(uint32_t table_index, uint32_t sig_index,
291 : Node** args, wasm::WasmCodePosition position);
292 :
293 : Node* Invert(Node* node);
294 :
295 : Node* GetGlobal(uint32_t index);
296 : Node* SetGlobal(uint32_t index, Node* val);
297 : Node* GetTable(uint32_t table_index, Node* index,
298 : wasm::WasmCodePosition position);
299 : Node* SetTable(uint32_t table_index, Node* index, Node* val,
300 : wasm::WasmCodePosition position);
301 : //-----------------------------------------------------------------------
302 : // Operations that concern the linear memory.
303 : //-----------------------------------------------------------------------
304 : Node* CurrentMemoryPages();
305 : Node* TraceMemoryOperation(bool is_store, MachineRepresentation, Node* index,
306 : uint32_t offset, wasm::WasmCodePosition);
307 : Node* LoadMem(wasm::ValueType type, MachineType memtype, Node* index,
308 : uint32_t offset, uint32_t alignment,
309 : wasm::WasmCodePosition position);
310 : Node* StoreMem(MachineRepresentation mem_rep, Node* index, uint32_t offset,
311 : uint32_t alignment, Node* val, wasm::WasmCodePosition position,
312 : wasm::ValueType type);
313 : static void PrintDebugName(Node* node);
314 :
315 : void set_instance_node(Node* instance_node) {
316 : this->instance_node_ = instance_node;
317 : }
318 :
319 : Node* Control() {
320 : DCHECK_NOT_NULL(*control_);
321 7570901 : return *control_;
322 : }
323 : Node* Effect() {
324 : DCHECK_NOT_NULL(*effect_);
325 7205170 : return *effect_;
326 : }
327 : Node* SetControl(Node* node) {
328 1146334 : *control_ = node;
329 : return node;
330 : }
331 : Node* SetEffect(Node* node) {
332 6092533 : *effect_ = node;
333 : return node;
334 : }
335 :
336 2721395 : void set_control_ptr(Node** control) { this->control_ = control; }
337 :
338 2721395 : void set_effect_ptr(Node** effect) { this->effect_ = effect; }
339 :
340 : Node* GetImportedMutableGlobals();
341 :
342 : void GetGlobalBaseAndOffset(MachineType mem_type, const wasm::WasmGlobal&,
343 : Node** base_node, Node** offset_node);
344 :
345 : void GetBaseAndOffsetForImportedMutableAnyRefGlobal(
346 : const wasm::WasmGlobal& global, Node** base, Node** offset);
347 :
348 : void BoundsCheckTable(uint32_t table_index, Node* index,
349 : wasm::WasmCodePosition position,
350 : wasm::TrapReason trap_reason, Node** base_node);
351 :
352 : void GetTableBaseAndOffset(uint32_t table_index, Node* index,
353 : wasm::WasmCodePosition position, Node** base_node,
354 : Node** offset_node);
355 :
356 : // Utilities to manipulate sets of instance cache nodes.
357 : void InitInstanceCache(WasmInstanceCacheNodes* instance_cache);
358 : void PrepareInstanceCacheForLoop(WasmInstanceCacheNodes* instance_cache,
359 : Node* control);
360 : void NewInstanceCacheMerge(WasmInstanceCacheNodes* to,
361 : WasmInstanceCacheNodes* from, Node* merge);
362 : void MergeInstanceCacheInto(WasmInstanceCacheNodes* to,
363 : WasmInstanceCacheNodes* from, Node* merge);
364 :
365 : void set_instance_cache(WasmInstanceCacheNodes* instance_cache) {
366 1574877 : this->instance_cache_ = instance_cache;
367 : }
368 :
369 : wasm::FunctionSig* GetFunctionSignature() { return sig_; }
370 :
371 : V8_EXPORT_PRIVATE void LowerInt64();
372 :
373 : V8_EXPORT_PRIVATE void SimdScalarLoweringForTesting();
374 :
375 : void SetSourcePosition(Node* node, wasm::WasmCodePosition position);
376 :
377 : Node* S128Zero();
378 : Node* S1x4Zero();
379 : Node* S1x8Zero();
380 : Node* S1x16Zero();
381 :
382 : Node* SimdOp(wasm::WasmOpcode opcode, Node* const* inputs);
383 :
384 : Node* SimdLaneOp(wasm::WasmOpcode opcode, uint8_t lane, Node* const* inputs);
385 :
386 : Node* SimdShiftOp(wasm::WasmOpcode opcode, uint8_t shift,
387 : Node* const* inputs);
388 :
389 : Node* Simd8x16ShuffleOp(const uint8_t shuffle[16], Node* const* inputs);
390 :
391 : Node* AtomicOp(wasm::WasmOpcode opcode, Node* const* inputs,
392 : uint32_t alignment, uint32_t offset,
393 : wasm::WasmCodePosition position);
394 :
395 : // Returns a pointer to the dropped_data_segments array. Traps if the data
396 : // segment is active or has been dropped.
397 : Node* CheckDataSegmentIsPassiveAndNotDropped(uint32_t data_segment_index,
398 : wasm::WasmCodePosition position);
399 : Node* CheckElemSegmentIsPassiveAndNotDropped(uint32_t elem_segment_index,
400 : wasm::WasmCodePosition position);
401 : Node* MemoryInit(uint32_t data_segment_index, Node* dst, Node* src,
402 : Node* size, wasm::WasmCodePosition position);
403 : Node* MemoryCopy(Node* dst, Node* src, Node* size,
404 : wasm::WasmCodePosition position);
405 : Node* DataDrop(uint32_t data_segment_index, wasm::WasmCodePosition position);
406 : Node* MemoryFill(Node* dst, Node* fill, Node* size,
407 : wasm::WasmCodePosition position);
408 :
409 : Node* TableInit(uint32_t table_index, uint32_t elem_segment_index, Node* dst,
410 : Node* src, Node* size, wasm::WasmCodePosition position);
411 : Node* ElemDrop(uint32_t elem_segment_index, wasm::WasmCodePosition position);
412 : Node* TableCopy(uint32_t table_src_index, uint32_t table_dst_index, Node* dst,
413 : Node* src, Node* size, wasm::WasmCodePosition position);
414 :
415 : bool has_simd() const { return has_simd_; }
416 :
417 : const wasm::WasmModule* module() { return env_ ? env_->module : nullptr; }
418 :
419 : wasm::UseTrapHandler use_trap_handler() const {
420 517897 : return env_ ? env_->use_trap_handler : wasm::kNoTrapHandler;
421 : }
422 :
423 : MachineGraph* mcgraph() { return mcgraph_; }
424 : Graph* graph();
425 :
426 : void AddBytecodePositionDecorator(NodeOriginTable* node_origins,
427 : wasm::Decoder* decoder);
428 :
429 : void RemoveBytecodePositionDecorator();
430 :
431 : protected:
432 : static const int kDefaultBufferSize = 16;
433 :
434 : Zone* const zone_;
435 : MachineGraph* const mcgraph_;
436 : wasm::CompilationEnv* const env_;
437 :
438 : Node** control_ = nullptr;
439 : Node** effect_ = nullptr;
440 : WasmInstanceCacheNodes* instance_cache_ = nullptr;
441 :
442 : SetOncePointer<Node> instance_node_;
443 : SetOncePointer<Node> globals_start_;
444 : SetOncePointer<Node> imported_mutable_globals_;
445 : SetOncePointer<Node> stack_check_code_node_;
446 : SetOncePointer<const Operator> stack_check_call_operator_;
447 :
448 : Node** cur_buffer_;
449 : size_t cur_bufsize_;
450 : Node* def_buffer_[kDefaultBufferSize];
451 : bool has_simd_ = false;
452 : bool needs_stack_check_ = false;
453 : const bool untrusted_code_mitigations_ = true;
454 :
455 : wasm::FunctionSig* const sig_;
456 :
457 : compiler::WasmDecorator* decorator_ = nullptr;
458 :
459 : compiler::SourcePositionTable* const source_position_table_ = nullptr;
460 :
461 : Node* NoContextConstant();
462 :
463 : Node* MemBuffer(uint32_t offset);
464 : // BoundsCheckMem receives a uint32 {index} node and returns a ptrsize index.
465 : Node* BoundsCheckMem(uint8_t access_size, Node* index, uint32_t offset,
466 : wasm::WasmCodePosition, EnforceBoundsCheck);
467 : // Check that the range [start, start + size) is in the range [0, max).
468 : // Also updates *size with the valid range. Returns true if the range is
469 : // partially out-of-bounds, traps if it is completely out-of-bounds.
470 : Node* BoundsCheckRange(Node* start, Node** size, Node* max,
471 : wasm::WasmCodePosition);
472 : // BoundsCheckMemRange receives a uint32 {start} and {size}, and checks if it
473 : // is in bounds. Also updates *size with the valid range, and converts *start
474 : // to a pointer into memory at that index. Returns true if the range is
475 : // partially out-of-bounds, traps if it is completely out-of-bounds.
476 : Node* BoundsCheckMemRange(Node** start, Node** size, wasm::WasmCodePosition);
477 :
478 : Node* CheckBoundsAndAlignment(uint8_t access_size, Node* index,
479 : uint32_t offset, wasm::WasmCodePosition);
480 :
481 : Node* Uint32ToUintptr(Node*);
482 : const Operator* GetSafeLoadOperator(int offset, wasm::ValueType type);
483 : const Operator* GetSafeStoreOperator(int offset, wasm::ValueType type);
484 : Node* BuildChangeEndiannessStore(Node* node, MachineRepresentation rep,
485 : wasm::ValueType wasmtype = wasm::kWasmStmt);
486 : Node* BuildChangeEndiannessLoad(Node* node, MachineType type,
487 : wasm::ValueType wasmtype = wasm::kWasmStmt);
488 :
489 : Node* MaskShiftCount32(Node* node);
490 : Node* MaskShiftCount64(Node* node);
491 :
492 : enum IsReturnCall : bool { kReturnCall = true, kCallContinues = false };
493 :
494 : template <typename... Args>
495 : Node* BuildCCall(MachineSignature* sig, Node* function, Args... args);
496 : Node* BuildCallNode(wasm::FunctionSig* sig, Node** args,
497 : wasm::WasmCodePosition position, Node* instance_node,
498 : const Operator* op);
499 : // Special implementation for CallIndirect for table 0.
500 : Node* BuildIndirectCall(uint32_t sig_index, Node** args, Node*** rets,
501 : wasm::WasmCodePosition position,
502 : IsReturnCall continuation);
503 : Node* BuildIndirectCall(uint32_t table_index, uint32_t sig_index, Node** args,
504 : Node*** rets, wasm::WasmCodePosition position,
505 : IsReturnCall continuation);
506 : Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args, Node*** rets,
507 : wasm::WasmCodePosition position, Node* instance_node,
508 : UseRetpoline use_retpoline);
509 : Node* BuildWasmReturnCall(wasm::FunctionSig* sig, Node** args,
510 : wasm::WasmCodePosition position,
511 : Node* instance_node, UseRetpoline use_retpoline);
512 : Node* BuildImportCall(wasm::FunctionSig* sig, Node** args, Node*** rets,
513 : wasm::WasmCodePosition position, int func_index,
514 : IsReturnCall continuation);
515 : Node* BuildImportCall(wasm::FunctionSig* sig, Node** args, Node*** rets,
516 : wasm::WasmCodePosition position, Node* func_index,
517 : IsReturnCall continuation);
518 :
519 : Node* BuildF32CopySign(Node* left, Node* right);
520 : Node* BuildF64CopySign(Node* left, Node* right);
521 :
522 : Node* BuildIntConvertFloat(Node* input, wasm::WasmCodePosition position,
523 : wasm::WasmOpcode);
524 : Node* BuildI32Ctz(Node* input);
525 : Node* BuildI32Popcnt(Node* input);
526 : Node* BuildI64Ctz(Node* input);
527 : Node* BuildI64Popcnt(Node* input);
528 : Node* BuildBitCountingCall(Node* input, ExternalReference ref,
529 : MachineRepresentation input_type);
530 :
531 : Node* BuildCFuncInstruction(ExternalReference ref, MachineType type,
532 : Node* input0, Node* input1 = nullptr);
533 : Node* BuildF32Trunc(Node* input);
534 : Node* BuildF32Floor(Node* input);
535 : Node* BuildF32Ceil(Node* input);
536 : Node* BuildF32NearestInt(Node* input);
537 : Node* BuildF64Trunc(Node* input);
538 : Node* BuildF64Floor(Node* input);
539 : Node* BuildF64Ceil(Node* input);
540 : Node* BuildF64NearestInt(Node* input);
541 : Node* BuildI32Rol(Node* left, Node* right);
542 : Node* BuildI64Rol(Node* left, Node* right);
543 :
544 : Node* BuildF64Acos(Node* input);
545 : Node* BuildF64Asin(Node* input);
546 : Node* BuildF64Pow(Node* left, Node* right);
547 : Node* BuildF64Mod(Node* left, Node* right);
548 :
549 : Node* BuildIntToFloatConversionInstruction(
550 : Node* input, ExternalReference ref,
551 : MachineRepresentation parameter_representation,
552 : const MachineType result_type);
553 : Node* BuildF32SConvertI64(Node* input);
554 : Node* BuildF32UConvertI64(Node* input);
555 : Node* BuildF64SConvertI64(Node* input);
556 : Node* BuildF64UConvertI64(Node* input);
557 :
558 : Node* BuildCcallConvertFloat(Node* input, wasm::WasmCodePosition position,
559 : wasm::WasmOpcode opcode);
560 :
561 : Node* BuildI32DivS(Node* left, Node* right, wasm::WasmCodePosition position);
562 : Node* BuildI32RemS(Node* left, Node* right, wasm::WasmCodePosition position);
563 : Node* BuildI32DivU(Node* left, Node* right, wasm::WasmCodePosition position);
564 : Node* BuildI32RemU(Node* left, Node* right, wasm::WasmCodePosition position);
565 :
566 : Node* BuildI64DivS(Node* left, Node* right, wasm::WasmCodePosition position);
567 : Node* BuildI64RemS(Node* left, Node* right, wasm::WasmCodePosition position);
568 : Node* BuildI64DivU(Node* left, Node* right, wasm::WasmCodePosition position);
569 : Node* BuildI64RemU(Node* left, Node* right, wasm::WasmCodePosition position);
570 : Node* BuildDiv64Call(Node* left, Node* right, ExternalReference ref,
571 : MachineType result_type, wasm::TrapReason trap_zero,
572 : wasm::WasmCodePosition position);
573 :
574 : Node* BuildChangeInt32ToIntPtr(Node* value);
575 : Node* BuildChangeInt32ToSmi(Node* value);
576 : Node* BuildChangeUint31ToSmi(Node* value);
577 : Node* BuildSmiShiftBitsConstant();
578 : Node* BuildChangeSmiToInt32(Node* value);
579 : // generates {index > max ? Smi(max) : Smi(index)}
580 : Node* BuildConvertUint32ToSmiWithSaturation(Node* index, uint32_t maxval);
581 :
582 : // Asm.js specific functionality.
583 : Node* BuildI32AsmjsSConvertF32(Node* input);
584 : Node* BuildI32AsmjsSConvertF64(Node* input);
585 : Node* BuildI32AsmjsUConvertF32(Node* input);
586 : Node* BuildI32AsmjsUConvertF64(Node* input);
587 : Node* BuildI32AsmjsDivS(Node* left, Node* right);
588 : Node* BuildI32AsmjsRemS(Node* left, Node* right);
589 : Node* BuildI32AsmjsDivU(Node* left, Node* right);
590 : Node* BuildI32AsmjsRemU(Node* left, Node* right);
591 : Node* BuildAsmjsLoadMem(MachineType type, Node* index);
592 : Node* BuildAsmjsStoreMem(MachineType type, Node* index, Node* val);
593 :
594 : void BuildEncodeException32BitValue(Node* values_array, uint32_t* index,
595 : Node* value);
596 : Node* BuildDecodeException32BitValue(Node* values_array, uint32_t* index);
597 : Node* BuildDecodeException64BitValue(Node* values_array, uint32_t* index);
598 :
599 414837 : Node** Realloc(Node* const* buffer, size_t old_count, size_t new_count) {
600 414837 : Node** buf = Buffer(new_count);
601 414889 : if (buf != buffer) memcpy(buf, buffer, old_count * sizeof(Node*));
602 414889 : return buf;
603 : }
604 :
605 : Node* BuildLoadBuiltinFromInstance(int builtin_index);
606 :
607 : //-----------------------------------------------------------------------
608 : // Operations involving the CEntry, a dependency we want to remove
609 : // to get off the GC heap.
610 : //-----------------------------------------------------------------------
611 : Node* BuildCallToRuntime(Runtime::FunctionId f, Node** parameters,
612 : int parameter_count);
613 :
614 : Node* BuildCallToRuntimeWithContext(Runtime::FunctionId f, Node* js_context,
615 : Node** parameters, int parameter_count,
616 : Node** effect, Node* control);
617 : TrapId GetTrapIdForTrap(wasm::TrapReason reason);
618 : };
619 :
620 : V8_EXPORT_PRIVATE CallDescriptor* GetWasmCallDescriptor(
621 : Zone* zone, wasm::FunctionSig* signature,
622 : WasmGraphBuilder::UseRetpoline use_retpoline =
623 : WasmGraphBuilder::kNoRetpoline,
624 : WasmGraphBuilder::ExtraCallableParam callable_param =
625 : WasmGraphBuilder::kNoExtraCallableParam);
626 :
627 : V8_EXPORT_PRIVATE CallDescriptor* GetI32WasmCallDescriptor(
628 : Zone* zone, CallDescriptor* call_descriptor);
629 :
630 : V8_EXPORT_PRIVATE CallDescriptor* GetI32WasmCallDescriptorForSimd(
631 : Zone* zone, CallDescriptor* call_descriptor);
632 :
633 : AssemblerOptions WasmAssemblerOptions();
634 : AssemblerOptions WasmStubAssemblerOptions();
635 :
636 : } // namespace compiler
637 : } // namespace internal
638 : } // namespace v8
639 :
640 : #endif // V8_COMPILER_WASM_COMPILER_H_
|