wasm-compiler.h 29 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_COMPILER_WASM_COMPILER_H_
#define V8_COMPILER_WASM_COMPILER_H_

8
#include <memory>
9
#include <utility>
10

11 12
// Clients of this interface shouldn't depend on lots of compiler internals.
// Do not include anything from src/compiler here!
13
#include "src/runtime/runtime.h"
14
#include "src/wasm/function-body-decoder.h"
15
#include "src/wasm/function-compiler.h"
16
#include "src/wasm/wasm-module.h"
17
#include "src/wasm/wasm-opcodes.h"
18
#include "src/wasm/wasm-result.h"
19
#include "src/zone/zone.h"
20 21 22

namespace v8 {
namespace internal {
23
struct AssemblerOptions;
24
class OptimizedCompilationJob;
25

26 27
namespace compiler {
// Forward declarations for some compiler data structures.
28
class CallDescriptor;
29
class Graph;
30
class MachineGraph;
31
class Node;
32
class NodeOriginTable;
33
class Operator;
34
class SourcePositionTable;
35
class WasmDecorator;
36
class WasmGraphAssembler;
37
enum class TrapId : uint32_t;
38
struct Int64LoweringSpecialCase;
39
}  // namespace compiler
40 41

namespace wasm {
42
struct DecodeStruct;
43
// Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}.
44 45
using TFNode = compiler::Node;
using TFGraph = compiler::MachineGraph;
46
class WasmCode;
47
class WasmFeatures;
48
enum class LoadTransformationKind : uint8_t;
49
}  // namespace wasm
50 51

namespace compiler {
52

53 54 55
wasm::WasmCompilationResult ExecuteTurbofanWasmCompilation(
    wasm::WasmEngine*, wasm::CompilationEnv*, const wasm::FunctionBody&,
    int func_index, Counters*, wasm::WasmFeatures* detected);
56

57
// Calls to Wasm imports are handled in several different ways, depending on the
58 59
// type of the target function/callable and whether the signature matches the
// argument arity.
60
enum class WasmImportCallKind : uint8_t {
61 62 63 64 65 66 67 68 69
  kLinkError,                           // static Wasm->Wasm type error
  kRuntimeTypeError,                    // runtime Wasm->JS type error
  kWasmToCapi,                          // fast Wasm->C-API call
  kWasmToWasm,                          // fast Wasm->Wasm call
  kJSFunctionArityMatch,                // fast Wasm->JS call
  kJSFunctionArityMismatch,             // Wasm->JS, needs adapter frame
  kJSFunctionArityMismatchSkipAdaptor,  // Wasm->JS, arity mismatch calling
                                        // strict mode function where we don't
                                        // need the ArgumentsAdaptorTrampoline.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
  // Math functions imported from JavaScript that are intrinsified
  kFirstMathIntrinsic,
  kF64Acos = kFirstMathIntrinsic,
  kF64Asin,
  kF64Atan,
  kF64Cos,
  kF64Sin,
  kF64Tan,
  kF64Exp,
  kF64Log,
  kF64Atan2,
  kF64Pow,
  kF64Ceil,
  kF64Floor,
  kF64Sqrt,
  kF64Min,
  kF64Max,
  kF64Abs,
  kF32Min,
  kF32Max,
  kF32Abs,
  kF32Ceil,
  kF32Floor,
  kF32Sqrt,
  kF32ConvertF64,
  kLastMathIntrinsic = kF32ConvertF64,
  // For everything else, there's the call builtin.
  kUseCallBuiltin
98 99
};

100
constexpr WasmImportCallKind kDefaultImportCallKind =
101
    WasmImportCallKind::kJSFunctionArityMatch;
102

103 104 105 106 107
// Resolves which import call wrapper is required for the given JS callable.
// Returns the kind of wrapper need and the ultimate target callable. Note that
// some callables (e.g. a {WasmExportedFunction} or {WasmJSFunction}) just wrap
// another target, which is why the ultimate target is returned as well.
V8_EXPORT_PRIVATE std::pair<WasmImportCallKind, Handle<JSReceiver>>
108
ResolveWasmImportCall(Handle<JSReceiver> callable, const wasm::FunctionSig* sig,
109
                      const wasm::WasmFeatures& enabled_features);
110

111
// Compiles an import call wrapper, which allows Wasm to call imports.
112 113
V8_EXPORT_PRIVATE wasm::WasmCompilationResult CompileWasmImportCallWrapper(
    wasm::WasmEngine*, wasm::CompilationEnv* env, WasmImportCallKind,
114
    const wasm::FunctionSig*, bool source_positions, int expected_arity);
115

116
// Compiles a host call wrapper, which allows Wasm to call host functions.
117 118
wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::WasmEngine*,
                                           wasm::NativeModule*,
119 120
                                           const wasm::FunctionSig*,
                                           Address address);
121

122 123
// Returns an OptimizedCompilationJob object for a JS to Wasm wrapper.
std::unique_ptr<OptimizedCompilationJob> NewJSToWasmCompilationJob(
124 125 126
    Isolate* isolate, wasm::WasmEngine* wasm_engine,
    const wasm::FunctionSig* sig, bool is_import,
    const wasm::WasmFeatures& enabled_features);
127

128 129 130
// Compiles a stub with JS linkage that serves as an adapter for function
// objects constructed via {WebAssembly.Function}. It performs a round-trip
// simulating a JS-to-Wasm-to-JS coercion of parameter and return values.
131
MaybeHandle<Code> CompileJSToJSWrapper(Isolate*, const wasm::FunctionSig*);
132

133
enum CWasmEntryParameters {
134
  kCodeEntry,
135
  kObjectRef,
136
  kArgumentsBuffer,
137
  kCEntryFp,
138 139 140 141
  // marker:
  kNumParameters
};

142 143
// Compiles a stub with C++ linkage, to be called from Execution::CallWasm,
// which knows how to feed it its parameters.
144 145
V8_EXPORT_PRIVATE Handle<Code> CompileCWasmEntry(Isolate*,
                                                 const wasm::FunctionSig*);
146

147
// Values from the instance object are cached between Wasm-level function calls.
148
// This struct allows the SSA environment handling this cache to be defined
149
// and manipulated in wasm-compiler.{h,cc} instead of inside the Wasm decoder.
150 151
// (Note that currently, the globals base is immutable, so not cached here.)
struct WasmInstanceCacheNodes {
152 153
  Node* mem_start;
  Node* mem_size;
154
  Node* mem_mask;
155 156
};

157 158
// Abstracts details of building TurboFan graph nodes for wasm to separate
// the wasm decoder from the internal details of TurboFan.
159 160
class WasmGraphBuilder {
 public:
161
  enum EnforceBoundsCheck : bool {  // --
162 163 164
    kNeedsBoundsCheck = true,
    kCanOmitBoundsCheck = false
  };
165 166 167 168
  enum UseRetpoline : bool {  // --
    kRetpoline = true,
    kNoRetpoline = false
  };
169 170 171 172
  enum CheckForNull : bool {  // --
    kWithNullCheck = true,
    kWithoutNullCheck = false
  };
173 174 175 176 177 178 179 180
  enum CheckForI31 : bool {  // --
    kWithI31Check = true,
    kNoI31Check = false
  };
  enum RttIsI31 : bool {  // --
    kRttIsI31 = true,
    kRttIsNotI31 = false
  };
181

182 183
  V8_EXPORT_PRIVATE WasmGraphBuilder(
      wasm::CompilationEnv* env, Zone* zone, MachineGraph* mcgraph,
184 185
      const wasm::FunctionSig* sig,
      compiler::SourcePositionTable* spt = nullptr);
186

187 188
  V8_EXPORT_PRIVATE ~WasmGraphBuilder();

189 190 191 192 193
  //-----------------------------------------------------------------------
  // Operations independent of {control} or {effect}.
  //-----------------------------------------------------------------------
  Node* Error();
  Node* Start(unsigned params);
194
  Node* Param(unsigned index);
195
  Node* Loop(Node* entry);
196 197
  Node* TerminateLoop(Node* effect, Node* control);
  Node* TerminateThrow(Node* effect, Node* control);
198
  Node* Merge(unsigned count, Node** controls);
199
  Node* Phi(wasm::ValueType type, unsigned count, Node** vals_and_control);
200 201
  Node* CreateOrMergeIntoPhi(MachineRepresentation rep, Node* merge,
                             Node* tnode, Node* fnode);
202
  Node* CreateOrMergeIntoEffectPhi(Node* merge, Node* tnode, Node* fnode);
203
  Node* EffectPhi(unsigned count, Node** effects_and_control);
204
  Node* RefNull();
205
  Node* RefFunc(uint32_t function_index);
206
  Node* RefAsNonNull(Node* arg, wasm::WasmCodePosition position);
207
  Node* Uint32Constant(uint32_t value);
208 209
  Node* Int32Constant(int32_t value);
  Node* Int64Constant(int64_t value);
210
  Node* IntPtrConstant(intptr_t value);
211 212
  Node* Float32Constant(float value);
  Node* Float64Constant(double value);
213
  Node* Simd128Constant(const uint8_t value[16]);
214 215 216 217
  Node* Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
              wasm::WasmCodePosition position = wasm::kNoCodePosition);
  Node* Unop(wasm::WasmOpcode opcode, Node* input,
             wasm::WasmCodePosition position = wasm::kNoCodePosition);
218
  Node* MemoryGrow(Node* input);
219
  Node* Throw(uint32_t exception_index, const wasm::WasmException* exception,
220
              const Vector<Node*> values, wasm::WasmCodePosition position);
221
  Node* Rethrow(Node* except_obj);
222 223
  Node* ExceptionTagEqual(Node* caught_tag, Node* expected_tag);
  Node* LoadExceptionTagFromTable(uint32_t exception_index);
224
  Node* GetExceptionTag(Node* except_obj, wasm::WasmCodePosition);
225 226 227
  Node* GetExceptionValues(Node* except_obj,
                           const wasm::WasmException* exception,
                           Vector<Node*> values_out);
228
  bool IsPhiWithMerge(Node* phi, Node* merge);
229
  bool ThrowsException(Node* node, Node** if_success, Node** if_exception);
230
  void AppendToMerge(Node* merge, Node* from);
231
  void AppendToPhi(Node* phi, Node* from);
232

233
  void StackCheck(wasm::WasmCodePosition);
234

235 236
  void PatchInStackCheckIfNeeded();

237 238 239
  //-----------------------------------------------------------------------
  // Operations that read and/or write {control} and {effect}.
  //-----------------------------------------------------------------------
240 241 242 243
  Node* BranchNoHint(Node* cond, Node** true_node, Node** false_node);
  Node* BranchExpectTrue(Node* cond, Node** true_node, Node** false_node);
  Node* BranchExpectFalse(Node* cond, Node** true_node, Node** false_node);

244 245 246 247 248 249 250 251 252 253 254 255 256
  Node* TrapIfTrue(wasm::TrapReason reason, Node* cond,
                   wasm::WasmCodePosition position);
  Node* TrapIfFalse(wasm::TrapReason reason, Node* cond,
                    wasm::WasmCodePosition position);
  Node* TrapIfEq32(wasm::TrapReason reason, Node* node, int32_t val,
                   wasm::WasmCodePosition position);
  Node* ZeroCheck32(wasm::TrapReason reason, Node* node,
                    wasm::WasmCodePosition position);
  Node* TrapIfEq64(wasm::TrapReason reason, Node* node, int64_t val,
                   wasm::WasmCodePosition position);
  Node* ZeroCheck64(wasm::TrapReason reason, Node* node,
                    wasm::WasmCodePosition position);

257 258 259
  Node* Switch(unsigned count, Node* key);
  Node* IfValue(int32_t value, Node* sw);
  Node* IfDefault(Node* sw);
260
  Node* Return(Vector<Node*> nodes);
261 262 263
  template <typename... Nodes>
  Node* Return(Node* fst, Nodes*... more) {
    Node* arr[] = {fst, more...};
264
    return Return(ArrayVector(arr));
265
  }
266 267 268 269

  Node* TraceFunctionEntry(wasm::WasmCodePosition position);
  Node* TraceFunctionExit(Vector<Node*> vals, wasm::WasmCodePosition position);

270
  Node* Trap(wasm::TrapReason reason, wasm::WasmCodePosition position);
271

272
  Node* CallDirect(uint32_t index, Vector<Node*> args, Vector<Node*> rets,
273
                   wasm::WasmCodePosition position);
274 275 276
  Node* CallIndirect(uint32_t table_index, uint32_t sig_index,
                     Vector<Node*> args, Vector<Node*> rets,
                     wasm::WasmCodePosition position);
277 278
  Node* CallRef(uint32_t sig_index, Vector<Node*> args, Vector<Node*> rets,
                CheckForNull null_check, wasm::WasmCodePosition position);
279

280
  Node* ReturnCall(uint32_t index, Vector<Node*> args,
281
                   wasm::WasmCodePosition position);
282
  Node* ReturnCallIndirect(uint32_t table_index, uint32_t sig_index,
283
                           Vector<Node*> args, wasm::WasmCodePosition position);
284 285 286
  Node* ReturnCallRef(uint32_t sig_index, Vector<Node*> args,
                      CheckForNull null_check, wasm::WasmCodePosition position);

287 288 289
  // Return value is not expected to be used,
  // but we need it for compatibility with graph-builder-interface.
  Node* BrOnNull(Node* ref_object, Node** non_null_node, Node** null_node);
290

291 292
  Node* Invert(Node* node);

293 294
  Node* GlobalGet(uint32_t index);
  Node* GlobalSet(uint32_t index, Node* val);
295
  Node* TableGet(uint32_t table_index, Node* index,
296
                 wasm::WasmCodePosition position);
297
  Node* TableSet(uint32_t table_index, Node* index, Node* val,
298
                 wasm::WasmCodePosition position);
299 300 301
  //-----------------------------------------------------------------------
  // Operations that concern the linear memory.
  //-----------------------------------------------------------------------
302
  Node* CurrentMemoryPages();
303 304
  Node* TraceMemoryOperation(bool is_store, MachineRepresentation, Node* index,
                             uint32_t offset, wasm::WasmCodePosition);
305
  Node* LoadMem(wasm::ValueType type, MachineType memtype, Node* index,
306 307
                uint32_t offset, uint32_t alignment,
                wasm::WasmCodePosition position);
308
#if defined(V8_TARGET_BIG_ENDIAN) || defined(V8_TARGET_ARCH_S390_LE_SIM)
309
  Node* LoadTransformBigEndian(wasm::ValueType type, MachineType memtype,
310
                               wasm::LoadTransformationKind transform,
311 312
                               Node* index, uint32_t offset, uint32_t alignment,
                               wasm::WasmCodePosition position);
313 314
#endif
  Node* LoadTransform(wasm::ValueType type, MachineType memtype,
315 316 317
                      wasm::LoadTransformationKind transform, Node* index,
                      uint32_t offset, uint32_t alignment,
                      wasm::WasmCodePosition position);
318
  Node* StoreMem(MachineRepresentation mem_rep, Node* index, uint32_t offset,
319
                 uint32_t alignment, Node* val, wasm::WasmCodePosition position,
320
                 wasm::ValueType type);
321 322
  static void PrintDebugName(Node* node);

323 324
  void set_instance_node(Node* instance_node) {
    this->instance_node_ = instance_node;
325 326
  }

327 328
  Node* effect();
  Node* control();
329 330 331 332 333 334
  Node* SetEffect(Node* node);
  Node* SetControl(Node* node);
  void SetEffectControl(Node* effect, Node* control);
  Node* SetEffectControl(Node* effect_and_control) {
    SetEffectControl(effect_and_control, effect_and_control);
    return effect_and_control;
335
  }
336

337 338
  Node* GetImportedMutableGlobals();

339
  void GetGlobalBaseAndOffset(MachineType mem_type, const wasm::WasmGlobal&,
340
                              Node** base_node, Node** offset_node);
341

342
  void GetBaseAndOffsetForImportedMutableExternRefGlobal(
343 344
      const wasm::WasmGlobal& global, Node** base, Node** offset);

345 346 347 348 349 350 351 352 353 354 355
  // Utilities to manipulate sets of instance cache nodes.
  void InitInstanceCache(WasmInstanceCacheNodes* instance_cache);
  void PrepareInstanceCacheForLoop(WasmInstanceCacheNodes* instance_cache,
                                   Node* control);
  void NewInstanceCacheMerge(WasmInstanceCacheNodes* to,
                             WasmInstanceCacheNodes* from, Node* merge);
  void MergeInstanceCacheInto(WasmInstanceCacheNodes* to,
                              WasmInstanceCacheNodes* from, Node* merge);

  void set_instance_cache(WasmInstanceCacheNodes* instance_cache) {
    this->instance_cache_ = instance_cache;
356
  }
357

358
  const wasm::FunctionSig* GetFunctionSignature() { return sig_; }
359

360
  enum CallOrigin { kCalledFromWasm, kCalledFromJS };
361 362

  V8_EXPORT_PRIVATE void LowerInt64(CallOrigin origin);
363

364
  V8_EXPORT_PRIVATE void SimdScalarLoweringForTesting();
365

366
  void SetSourcePosition(Node* node, wasm::WasmCodePosition position);
367

368 369 370 371
  Node* S128Zero();
  Node* S1x4Zero();
  Node* S1x8Zero();
  Node* S1x16Zero();
372

373
  Node* SimdOp(wasm::WasmOpcode opcode, Node* const* inputs);
374

375
  Node* SimdLaneOp(wasm::WasmOpcode opcode, uint8_t lane, Node* const* inputs);
376

377
  Node* Simd8x16ShuffleOp(const uint8_t shuffle[16], Node* const* inputs);
378

379
  Node* AtomicOp(wasm::WasmOpcode opcode, Node* const* inputs,
380
                 uint32_t alignment, uint32_t offset,
381
                 wasm::WasmCodePosition position);
382
  Node* AtomicFence();
383

384 385
  Node* MemoryInit(uint32_t data_segment_index, Node* dst, Node* src,
                   Node* size, wasm::WasmCodePosition position);
386 387
  Node* MemoryCopy(Node* dst, Node* src, Node* size,
                   wasm::WasmCodePosition position);
388
  Node* DataDrop(uint32_t data_segment_index, wasm::WasmCodePosition position);
389 390 391
  Node* MemoryFill(Node* dst, Node* fill, Node* size,
                   wasm::WasmCodePosition position);

392 393
  Node* TableInit(uint32_t table_index, uint32_t elem_segment_index, Node* dst,
                  Node* src, Node* size, wasm::WasmCodePosition position);
394
  Node* ElemDrop(uint32_t elem_segment_index, wasm::WasmCodePosition position);
395
  Node* TableCopy(uint32_t table_dst_index, uint32_t table_src_index, Node* dst,
396
                  Node* src, Node* size, wasm::WasmCodePosition position);
397
  Node* TableGrow(uint32_t table_index, Node* value, Node* delta);
398
  Node* TableSize(uint32_t table_index);
399
  Node* TableFill(uint32_t table_index, Node* start, Node* value, Node* count);
400

401 402
  Node* StructNewWithRtt(uint32_t struct_index, const wasm::StructType* type,
                         Node* rtt, Vector<Node*> fields);
403
  Node* StructGet(Node* struct_object, const wasm::StructType* struct_type,
404
                  uint32_t field_index, CheckForNull null_check, bool is_signed,
405 406 407
                  wasm::WasmCodePosition position);
  Node* StructSet(Node* struct_object, const wasm::StructType* struct_type,
                  uint32_t field_index, Node* value, CheckForNull null_check,
408
                  wasm::WasmCodePosition position);
409 410
  Node* ArrayNewWithRtt(uint32_t array_index, const wasm::ArrayType* type,
                        Node* length, Node* initial_value, Node* rtt);
411 412
  void BoundsCheck(Node* array, Node* index, wasm::WasmCodePosition position);
  Node* ArrayGet(Node* array_object, const wasm::ArrayType* type, Node* index,
413 414
                 CheckForNull null_check, bool is_signed,
                 wasm::WasmCodePosition position);
415
  Node* ArraySet(Node* array_object, const wasm::ArrayType* type, Node* index,
416 417
                 Node* value, CheckForNull null_check,
                 wasm::WasmCodePosition position);
418
  Node* ArrayLen(Node* array_object, wasm::WasmCodePosition position);
419 420 421
  Node* I31New(Node* input);
  Node* I31GetS(Node* input);
  Node* I31GetU(Node* input);
422
  Node* RttCanon(wasm::HeapType type);
423
  Node* RttSub(wasm::HeapType type, Node* parent_rtt);
424 425
  Node* RefTest(Node* object, Node* rtt, CheckForNull null_check,
                CheckForI31 i31_check, RttIsI31 rtt_is_i31);
426
  Node* RefCast(Node* object, Node* rtt, CheckForNull null_check,
427
                CheckForI31 i31_check, RttIsI31 rtt_is_i31,
428
                wasm::WasmCodePosition position);
429 430 431 432
  Node* BrOnCast(Node* object, Node* rtt, CheckForNull null_check,
                 CheckForI31 i31_check, RttIsI31 rtt_is_i31,
                 Node** match_control, Node** match_effect,
                 Node** no_match_control, Node** no_match_effect);
433

434 435
  bool has_simd() const { return has_simd_; }

436 437 438
  wasm::UseTrapHandler use_trap_handler() const {
    return env_ ? env_->use_trap_handler : wasm::kNoTrapHandler;
  }
439

440
  MachineGraph* mcgraph() { return mcgraph_; }
441
  Graph* graph();
442

443 444 445 446 447
  void AddBytecodePositionDecorator(NodeOriginTable* node_origins,
                                    wasm::Decoder* decoder);

  void RemoveBytecodePositionDecorator();

448 449 450
 protected:
  Node* NoContextConstant();

451 452
  Node* BuildLoadIsolateRoot();

453
  Node* MemBuffer(uint32_t offset);
454 455 456
  // BoundsCheckMem receives a uint32 {index} node and returns a ptrsize index.
  Node* BoundsCheckMem(uint8_t access_size, Node* index, uint32_t offset,
                       wasm::WasmCodePosition, EnforceBoundsCheck);
457
  // Check that the range [start, start + size) is in the range [0, max).
458 459 460 461 462 463 464 465 466 467
  // Also updates *size with the valid range. Returns true if the range is
  // partially out-of-bounds, traps if it is completely out-of-bounds.
  Node* BoundsCheckRange(Node* start, Node** size, Node* max,
                         wasm::WasmCodePosition);
  // BoundsCheckMemRange receives a uint32 {start} and {size}, and checks if it
  // is in bounds. Also updates *size with the valid range, and converts *start
  // to a pointer into memory at that index. Returns true if the range is
  // partially out-of-bounds, traps if it is completely out-of-bounds.
  Node* BoundsCheckMemRange(Node** start, Node** size, wasm::WasmCodePosition);

468 469
  Node* CheckBoundsAndAlignment(uint8_t access_size, Node* index,
                                uint32_t offset, wasm::WasmCodePosition);
470

471
  Node* Uint32ToUintptr(Node*);
472
  const Operator* GetSafeLoadOperator(int offset, wasm::ValueType type);
473
  const Operator* GetSafeStoreOperator(int offset, wasm::ValueType type);
474
  Node* BuildChangeEndiannessStore(Node* node, MachineRepresentation rep,
475 476 477
                                   wasm::ValueType wasmtype = wasm::kWasmStmt);
  Node* BuildChangeEndiannessLoad(Node* node, MachineType type,
                                  wasm::ValueType wasmtype = wasm::kWasmStmt);
478

479 480 481
  Node* MaskShiftCount32(Node* node);
  Node* MaskShiftCount64(Node* node);

482 483
  enum IsReturnCall : bool { kReturnCall = true, kCallContinues = false };

484 485
  template <typename... Args>
  Node* BuildCCall(MachineSignature* sig, Node* function, Args... args);
486
  Node* BuildCallNode(const wasm::FunctionSig* sig, Vector<Node*> args,
487 488
                      wasm::WasmCodePosition position, Node* instance_node,
                      const Operator* op);
489 490 491 492
  // Helper function for {BuildIndirectCall}.
  void LoadIndirectFunctionTable(uint32_t table_index, Node** ift_size,
                                 Node** ift_sig_ids, Node** ift_targets,
                                 Node** ift_instances);
493 494 495
  Node* BuildIndirectCall(uint32_t table_index, uint32_t sig_index,
                          Vector<Node*> args, Vector<Node*> rets,
                          wasm::WasmCodePosition position,
496
                          IsReturnCall continuation);
497
  Node* BuildWasmCall(const wasm::FunctionSig* sig, Vector<Node*> args,
498 499
                      Vector<Node*> rets, wasm::WasmCodePosition position,
                      Node* instance_node, UseRetpoline use_retpoline);
500
  Node* BuildWasmReturnCall(const wasm::FunctionSig* sig, Vector<Node*> args,
501 502
                            wasm::WasmCodePosition position,
                            Node* instance_node, UseRetpoline use_retpoline);
503
  Node* BuildImportCall(const wasm::FunctionSig* sig, Vector<Node*> args,
504 505
                        Vector<Node*> rets, wasm::WasmCodePosition position,
                        int func_index, IsReturnCall continuation);
506
  Node* BuildImportCall(const wasm::FunctionSig* sig, Vector<Node*> args,
507 508
                        Vector<Node*> rets, wasm::WasmCodePosition position,
                        Node* func_index, IsReturnCall continuation);
509 510 511
  Node* BuildCallRef(uint32_t sig_index, Vector<Node*> args, Vector<Node*> rets,
                     CheckForNull null_check, IsReturnCall continuation,
                     wasm::WasmCodePosition position);
512
  Node* GetBuiltinPointerTarget(int builtin_id);
513

514 515
  Node* BuildF32CopySign(Node* left, Node* right);
  Node* BuildF64CopySign(Node* left, Node* right);
516

517 518
  Node* BuildIntConvertFloat(Node* input, wasm::WasmCodePosition position,
                             wasm::WasmOpcode);
519 520 521 522
  Node* BuildI32Ctz(Node* input);
  Node* BuildI32Popcnt(Node* input);
  Node* BuildI64Ctz(Node* input);
  Node* BuildI64Popcnt(Node* input);
523 524 525
  Node* BuildBitCountingCall(Node* input, ExternalReference ref,
                             MachineRepresentation input_type);

526 527
  Node* BuildCFuncInstruction(ExternalReference ref, MachineType type,
                              Node* input0, Node* input1 = nullptr);
528
  Node* BuildF32Trunc(Node* input);
529 530 531
  Node* BuildF32Floor(Node* input);
  Node* BuildF32Ceil(Node* input);
  Node* BuildF32NearestInt(Node* input);
532
  Node* BuildF64Trunc(Node* input);
533 534 535
  Node* BuildF64Floor(Node* input);
  Node* BuildF64Ceil(Node* input);
  Node* BuildF64NearestInt(Node* input);
536 537
  Node* BuildI32Rol(Node* left, Node* right);
  Node* BuildI64Rol(Node* left, Node* right);
538

539 540
  Node* BuildF64Acos(Node* input);
  Node* BuildF64Asin(Node* input);
541
  Node* BuildF64Pow(Node* left, Node* right);
542 543
  Node* BuildF64Mod(Node* left, Node* right);

544
  Node* BuildIntToFloatConversionInstruction(
545 546 547 548 549 550 551 552
      Node* input, ExternalReference ref,
      MachineRepresentation parameter_representation,
      const MachineType result_type);
  Node* BuildF32SConvertI64(Node* input);
  Node* BuildF32UConvertI64(Node* input);
  Node* BuildF64SConvertI64(Node* input);
  Node* BuildF64UConvertI64(Node* input);

553 554
  Node* BuildCcallConvertFloat(Node* input, wasm::WasmCodePosition position,
                               wasm::WasmOpcode opcode);
555 556 557 558 559 560 561 562 563 564

  Node* BuildI32DivS(Node* left, Node* right, wasm::WasmCodePosition position);
  Node* BuildI32RemS(Node* left, Node* right, wasm::WasmCodePosition position);
  Node* BuildI32DivU(Node* left, Node* right, wasm::WasmCodePosition position);
  Node* BuildI32RemU(Node* left, Node* right, wasm::WasmCodePosition position);

  Node* BuildI64DivS(Node* left, Node* right, wasm::WasmCodePosition position);
  Node* BuildI64RemS(Node* left, Node* right, wasm::WasmCodePosition position);
  Node* BuildI64DivU(Node* left, Node* right, wasm::WasmCodePosition position);
  Node* BuildI64RemU(Node* left, Node* right, wasm::WasmCodePosition position);
565
  Node* BuildDiv64Call(Node* left, Node* right, ExternalReference ref,
566
                       MachineType result_type, wasm::TrapReason trap_zero,
567
                       wasm::WasmCodePosition position);
568

569
  Node* BuildTruncateIntPtrToInt32(Node* value);
570
  Node* BuildChangeInt32ToIntPtr(Node* value);
571
  Node* BuildChangeInt32ToSmi(Node* value);
572
  Node* BuildChangeUint31ToSmi(Node* value);
573
  Node* BuildSmiShiftBitsConstant();
574
  Node* BuildSmiShiftBitsConstant32();
575
  Node* BuildChangeSmiToInt32(Node* value);
576
  Node* BuildChangeSmiToIntPtr(Node* value);
577 578
  // generates {index > max ? Smi(max) : Smi(index)}
  Node* BuildConvertUint32ToSmiWithSaturation(Node* index, uint32_t maxval);
579

580 581 582 583 584 585 586 587 588
  // Asm.js specific functionality.
  Node* BuildI32AsmjsSConvertF32(Node* input);
  Node* BuildI32AsmjsSConvertF64(Node* input);
  Node* BuildI32AsmjsUConvertF32(Node* input);
  Node* BuildI32AsmjsUConvertF64(Node* input);
  Node* BuildI32AsmjsDivS(Node* left, Node* right);
  Node* BuildI32AsmjsRemS(Node* left, Node* right);
  Node* BuildI32AsmjsDivU(Node* left, Node* right);
  Node* BuildI32AsmjsRemU(Node* left, Node* right);
589 590
  Node* BuildAsmjsLoadMem(MachineType type, Node* index);
  Node* BuildAsmjsStoreMem(MachineType type, Node* index, Node* val);
591

592
  // Wasm SIMD.
593
  Node* BuildF64x2Ceil(Node* input);
594
  Node* BuildF64x2Floor(Node* input);
595
  Node* BuildF64x2Trunc(Node* input);
596
  Node* BuildF64x2NearestInt(Node* input);
597
  Node* BuildF32x4Ceil(Node* input);
598
  Node* BuildF32x4Floor(Node* input);
599
  Node* BuildF32x4Trunc(Node* input);
600
  Node* BuildF32x4NearestInt(Node* input);
601

602
  void BuildEncodeException32BitValue(Node* values_array, uint32_t* index,
603
                                      Node* value);
604 605
  Node* BuildDecodeException32BitValue(Node* values_array, uint32_t* index);
  Node* BuildDecodeException64BitValue(Node* values_array, uint32_t* index);
606

607 608 609
  Node* BuildMultiReturnFixedArrayFromIterable(const wasm::FunctionSig* sig,
                                               Node* iterable, Node* context);

610 611 612 613
  Node* BuildLoadFunctionDataFromExportedFunction(Node* closure);
  Node* BuildLoadJumpTableOffsetFromExportedFunctionData(Node* function_data);
  Node* BuildLoadFunctionIndexFromExportedFunctionData(Node* function_data);

614
  //-----------------------------------------------------------------------
615
  // Operations involving the CEntry, a dependency we want to remove
616 617 618 619 620
  // to get off the GC heap.
  //-----------------------------------------------------------------------
  Node* BuildCallToRuntime(Runtime::FunctionId f, Node** parameters,
                           int parameter_count);

621
  Node* BuildCallToRuntimeWithContext(Runtime::FunctionId f, Node* js_context,
622
                                      Node** parameters, int parameter_count);
623
  TrapId GetTrapIdForTrap(wasm::TrapReason reason);
624

625 626 627 628 629 630 631
  void AddInt64LoweringReplacement(CallDescriptor* original,
                                   CallDescriptor* replacement);

  CallDescriptor* GetI32AtomicWaitCallDescriptor();

  CallDescriptor* GetI64AtomicWaitCallDescriptor();

632 633 634
  Node* StoreArgsInStackSlot(
      std::initializer_list<std::pair<MachineRepresentation, Node*>> args);

635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652
  std::unique_ptr<WasmGraphAssembler> gasm_;
  Zone* const zone_;
  MachineGraph* const mcgraph_;
  wasm::CompilationEnv* const env_;

  WasmInstanceCacheNodes* instance_cache_ = nullptr;

  SetOncePointer<Node> instance_node_;
  SetOncePointer<Node> globals_start_;
  SetOncePointer<Node> imported_mutable_globals_;
  SetOncePointer<Node> stack_check_code_node_;
  SetOncePointer<Node> isolate_root_node_;
  SetOncePointer<const Operator> stack_check_call_operator_;

  bool has_simd_ = false;
  bool needs_stack_check_ = false;
  const bool untrusted_code_mitigations_ = true;

653
  const wasm::FunctionSig* const sig_;
654 655 656 657 658 659

  compiler::WasmDecorator* decorator_ = nullptr;

  compiler::SourcePositionTable* const source_position_table_ = nullptr;

  std::unique_ptr<Int64LoweringSpecialCase> lowering_special_case_;
660 661
  CallDescriptor* i32_atomic_wait_descriptor_ = nullptr;
  CallDescriptor* i64_atomic_wait_descriptor_ = nullptr;
662
};
663

664 665
enum WasmCallKind { kWasmFunction, kWasmImportWrapper, kWasmCapiFunction };

666
V8_EXPORT_PRIVATE CallDescriptor* GetWasmCallDescriptor(
667
    Zone* zone, const wasm::FunctionSig* signature,
668
    WasmGraphBuilder::UseRetpoline use_retpoline =
669
        WasmGraphBuilder::kNoRetpoline,
670
    WasmCallKind kind = kWasmFunction);
671

672
V8_EXPORT_PRIVATE CallDescriptor* GetI32WasmCallDescriptor(
673
    Zone* zone, const CallDescriptor* call_descriptor);
674

675
V8_EXPORT_PRIVATE CallDescriptor* GetI32WasmCallDescriptorForSimd(
676
    Zone* zone, CallDescriptor* call_descriptor);
677

678
AssemblerOptions WasmAssemblerOptions();
679
AssemblerOptions WasmStubAssemblerOptions();
680

681 682 683 684 685
}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_WASM_COMPILER_H_