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