wasm-opcodes.cc 19.9 KB
Newer Older
1 2 3 4 5
// 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.

#include "src/wasm/wasm-opcodes.h"
6 7 8 9

#include <array>

#include "src/base/template-utils.h"
10
#include "src/codegen/signature.h"
11
#include "src/execution/messages.h"
12
#include "src/runtime/runtime.h"
13
#include "src/wasm/wasm-features.h"
14 15 16 17 18

namespace v8 {
namespace internal {
namespace wasm {

19 20 21 22 23 24 25
#define CASE_OP(name, str) \
  case kExpr##name:        \
    return str;
#define CASE_I32_OP(name, str) CASE_OP(I32##name, "i32." str)
#define CASE_I64_OP(name, str) CASE_OP(I64##name, "i64." str)
#define CASE_F32_OP(name, str) CASE_OP(F32##name, "f32." str)
#define CASE_F64_OP(name, str) CASE_OP(F64##name, "f64." str)
26
#define CASE_REF_OP(name, str) CASE_OP(Ref##name, "ref." str)
27
#define CASE_F64x2_OP(name, str) CASE_OP(F64x2##name, "f64x2." str)
28
#define CASE_F32x4_OP(name, str) CASE_OP(F32x4##name, "f32x4." str)
29
#define CASE_I64x2_OP(name, str) CASE_OP(I64x2##name, "i64x2." str)
30
#define CASE_I32x4_OP(name, str) CASE_OP(I32x4##name, "i32x4." str)
31 32
#define CASE_I16x8_OP(name, str) CASE_OP(I16x8##name, "i16x8." str)
#define CASE_I8x16_OP(name, str) CASE_OP(I8x16##name, "i8x16." str)
33
#define CASE_S128_OP(name, str) CASE_OP(S128##name, "s128." str)
34
#define CASE_S64x2_OP(name, str) CASE_OP(S64x2##name, "s64x2." str)
35
#define CASE_S32x4_OP(name, str) CASE_OP(S32x4##name, "s32x4." str)
36 37
#define CASE_S16x8_OP(name, str) CASE_OP(S16x8##name, "s16x8." str)
#define CASE_S8x16_OP(name, str) CASE_OP(S8x16##name, "s8x16." str)
38
#define CASE_S1x2_OP(name, str) CASE_OP(S1x2##name, "s1x2." str)
39 40 41
#define CASE_S1x4_OP(name, str) CASE_OP(S1x4##name, "s1x4." str)
#define CASE_S1x8_OP(name, str) CASE_OP(S1x8##name, "s1x8." str)
#define CASE_S1x16_OP(name, str) CASE_OP(S1x16##name, "s1x16." str)
42 43 44 45
#define CASE_INT_OP(name, str) CASE_I32_OP(name, str) CASE_I64_OP(name, str)
#define CASE_FLOAT_OP(name, str) CASE_F32_OP(name, str) CASE_F64_OP(name, str)
#define CASE_ALL_OP(name, str) CASE_FLOAT_OP(name, str) CASE_INT_OP(name, str)
#define CASE_SIMD_OP(name, str)                                              \
46 47 48 49 50
  CASE_F64x2_OP(name, str) CASE_I64x2_OP(name, str) CASE_F32x4_OP(name, str) \
      CASE_I32x4_OP(name, str) CASE_I16x8_OP(name, str)                      \
          CASE_I8x16_OP(name, str)
#define CASE_SIMDF_OP(name, str) \
  CASE_F32x4_OP(name, str) CASE_F64x2_OP(name, str)
51 52 53 54
#define CASE_SIMDI_OP(name, str) \
  CASE_I32x4_OP(name, str) CASE_I16x8_OP(name, str) CASE_I8x16_OP(name, str)
#define CASE_SIGN_OP(TYPE, name, str) \
  CASE_##TYPE##_OP(name##S, str "_s") CASE_##TYPE##_OP(name##U, str "_u")
55
#define CASE_UNSIGNED_OP(TYPE, name, str) CASE_##TYPE##_OP(name##U, str "_u")
56 57 58
#define CASE_ALL_SIGN_OP(name, str) \
  CASE_FLOAT_OP(name, str) CASE_SIGN_OP(INT, name, str)
#define CASE_CONVERT_OP(name, RES, SRC, src_suffix, str) \
59 60 61 62 63
  CASE_##RES##_OP(U##name##SRC, str "_" src_suffix "_u") \
      CASE_##RES##_OP(S##name##SRC, str "_" src_suffix "_s")
#define CASE_CONVERT_SAT_OP(name, RES, SRC, src_suffix, str)      \
  CASE_##RES##_OP(U##name##Sat##SRC, str "_sat_" src_suffix "_u") \
      CASE_##RES##_OP(S##name##Sat##SRC, str "_sat_" src_suffix "_s")
64 65 66 67
#define CASE_L32_OP(name, str)          \
  CASE_SIGN_OP(I32, name##8, str "8")   \
  CASE_SIGN_OP(I32, name##16, str "16") \
  CASE_I32_OP(name, str "32")
68 69 70 71
#define CASE_U32_OP(name, str)            \
  CASE_I32_OP(name, str "32")             \
  CASE_UNSIGNED_OP(I32, name##8, str "8") \
  CASE_UNSIGNED_OP(I32, name##16, str "16")
72 73 74 75 76 77
#define CASE_UNSIGNED_ALL_OP(name, str)     \
  CASE_U32_OP(name, str)                    \
  CASE_I64_OP(name, str "64")               \
  CASE_UNSIGNED_OP(I64, name##8, str "8")   \
  CASE_UNSIGNED_OP(I64, name##16, str "16") \
  CASE_UNSIGNED_OP(I64, name##32, str "32")
78

79 80
const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
  switch (opcode) {
81
    // clang-format off
82

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
    // Standard opcodes
    CASE_INT_OP(Eqz, "eqz")
    CASE_ALL_OP(Eq, "eq")
    CASE_ALL_OP(Ne, "ne")
    CASE_ALL_OP(Add, "add")
    CASE_ALL_OP(Sub, "sub")
    CASE_ALL_OP(Mul, "mul")
    CASE_ALL_SIGN_OP(Lt, "lt")
    CASE_ALL_SIGN_OP(Gt, "gt")
    CASE_ALL_SIGN_OP(Le, "le")
    CASE_ALL_SIGN_OP(Ge, "ge")
    CASE_INT_OP(Clz, "clz")
    CASE_INT_OP(Ctz, "ctz")
    CASE_INT_OP(Popcnt, "popcnt")
    CASE_ALL_SIGN_OP(Div, "div")
    CASE_SIGN_OP(INT, Rem, "rem")
    CASE_INT_OP(And, "and")
    CASE_INT_OP(Ior, "or")
    CASE_INT_OP(Xor, "xor")
    CASE_INT_OP(Shl, "shl")
    CASE_SIGN_OP(INT, Shr, "shr")
    CASE_INT_OP(Rol, "rol")
    CASE_INT_OP(Ror, "ror")
    CASE_FLOAT_OP(Abs, "abs")
    CASE_FLOAT_OP(Neg, "neg")
    CASE_FLOAT_OP(Ceil, "ceil")
    CASE_FLOAT_OP(Floor, "floor")
    CASE_FLOAT_OP(Trunc, "trunc")
    CASE_FLOAT_OP(NearestInt, "nearest")
    CASE_FLOAT_OP(Sqrt, "sqrt")
    CASE_FLOAT_OP(Min, "min")
    CASE_FLOAT_OP(Max, "max")
    CASE_FLOAT_OP(CopySign, "copysign")
116 117
    CASE_REF_OP(Null, "null")
    CASE_REF_OP(IsNull, "is_null")
118
    CASE_REF_OP(Func, "func")
119
    CASE_I32_OP(ConvertI64, "wrap_i64")
120 121 122 123 124
    CASE_CONVERT_OP(Convert, INT, F32, "f32", "trunc")
    CASE_CONVERT_OP(Convert, INT, F64, "f64", "trunc")
    CASE_CONVERT_OP(Convert, I64, I32, "i32", "extend")
    CASE_CONVERT_OP(Convert, F32, I32, "i32", "convert")
    CASE_CONVERT_OP(Convert, F32, I64, "i64", "convert")
125
    CASE_F32_OP(ConvertF64, "demote_f64")
126 127
    CASE_CONVERT_OP(Convert, F64, I32, "i32", "convert")
    CASE_CONVERT_OP(Convert, F64, I64, "i64", "convert")
128 129 130 131 132 133 134 135
    CASE_F64_OP(ConvertF32, "promote_f32")
    CASE_I32_OP(ReinterpretF32, "reinterpret_f32")
    CASE_I64_OP(ReinterpretF64, "reinterpret_f64")
    CASE_F32_OP(ReinterpretI32, "reinterpret_i32")
    CASE_F64_OP(ReinterpretI64, "reinterpret_i64")
    CASE_INT_OP(SExtendI8, "extend8_s")
    CASE_INT_OP(SExtendI16, "extend16_s")
    CASE_I64_OP(SExtendI32, "extend32_s")
136 137 138 139 140 141 142 143 144 145 146 147 148
    CASE_OP(Unreachable, "unreachable")
    CASE_OP(Nop, "nop")
    CASE_OP(Block, "block")
    CASE_OP(Loop, "loop")
    CASE_OP(If, "if")
    CASE_OP(Else, "else")
    CASE_OP(End, "end")
    CASE_OP(Br, "br")
    CASE_OP(BrIf, "br_if")
    CASE_OP(BrTable, "br_table")
    CASE_OP(Return, "return")
    CASE_OP(CallFunction, "call")
    CASE_OP(CallIndirect, "call_indirect")
149 150
    CASE_OP(ReturnCall, "return_call")
    CASE_OP(ReturnCallIndirect, "return_call_indirect")
151 152
    CASE_OP(Drop, "drop")
    CASE_OP(Select, "select")
153
    CASE_OP(SelectWithType, "select")
154 155 156
    CASE_OP(LocalGet, "local.get")
    CASE_OP(LocalSet, "local.set")
    CASE_OP(LocalTee, "local.tee")
157 158
    CASE_OP(GlobalGet, "global.get")
    CASE_OP(GlobalSet, "global.set")
159 160
    CASE_OP(TableGet, "table.get")
    CASE_OP(TableSet, "table.set")
161
    CASE_ALL_OP(Const, "const")
162 163
    CASE_OP(MemorySize, "memory.size")
    CASE_OP(MemoryGrow, "memory.grow")
164 165 166 167
    CASE_ALL_OP(LoadMem, "load")
    CASE_SIGN_OP(INT, LoadMem8, "load8")
    CASE_SIGN_OP(INT, LoadMem16, "load16")
    CASE_SIGN_OP(I64, LoadMem32, "load32")
168
    CASE_S128_OP(LoadMem, "load128")
169 170 171 172
    CASE_ALL_OP(StoreMem, "store")
    CASE_INT_OP(StoreMem8, "store8")
    CASE_INT_OP(StoreMem16, "store16")
    CASE_I64_OP(StoreMem32, "store32")
173
    CASE_S128_OP(StoreMem, "store128")
174

175
    // Exception handling opcodes.
176
    CASE_OP(Try, "try")
177
    CASE_OP(Catch, "catch")
178
    CASE_OP(Throw, "throw")
179
    CASE_OP(Rethrow, "rethrow")
180
    CASE_OP(BrOnExn, "br_on_exn")
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203

    // asm.js-only opcodes.
    CASE_F64_OP(Acos, "acos")
    CASE_F64_OP(Asin, "asin")
    CASE_F64_OP(Atan, "atan")
    CASE_F64_OP(Cos, "cos")
    CASE_F64_OP(Sin, "sin")
    CASE_F64_OP(Tan, "tan")
    CASE_F64_OP(Exp, "exp")
    CASE_F64_OP(Log, "log")
    CASE_F64_OP(Atan2, "atan2")
    CASE_F64_OP(Pow, "pow")
    CASE_F64_OP(Mod, "mod")
    CASE_F32_OP(AsmjsLoadMem, "asmjs_load")
    CASE_F64_OP(AsmjsLoadMem, "asmjs_load")
    CASE_L32_OP(AsmjsLoadMem, "asmjs_load")
    CASE_I32_OP(AsmjsStoreMem, "asmjs_store")
    CASE_F32_OP(AsmjsStoreMem, "asmjs_store")
    CASE_F64_OP(AsmjsStoreMem, "asmjs_store")
    CASE_I32_OP(AsmjsStoreMem8, "asmjs_store8")
    CASE_I32_OP(AsmjsStoreMem16, "asmjs_store16")
    CASE_SIGN_OP(I32, AsmjsDiv, "asmjs_div")
    CASE_SIGN_OP(I32, AsmjsRem, "asmjs_rem")
204 205 206 207
    CASE_I32_OP(AsmjsSConvertF32, "asmjs_convert_f32_s")
    CASE_I32_OP(AsmjsUConvertF32, "asmjs_convert_f32_u")
    CASE_I32_OP(AsmjsSConvertF64, "asmjs_convert_f64_s")
    CASE_I32_OP(AsmjsUConvertF64, "asmjs_convert_f64_u")
208

209 210 211 212 213 214
    // Numeric Opcodes.
    CASE_CONVERT_SAT_OP(Convert, I32, F32, "f32", "trunc")
    CASE_CONVERT_SAT_OP(Convert, I32, F64, "f64", "trunc")
    CASE_CONVERT_SAT_OP(Convert, I64, F32, "f32", "trunc")
    CASE_CONVERT_SAT_OP(Convert, I64, F64, "f64", "trunc")
    CASE_OP(MemoryInit, "memory.init")
215
    CASE_OP(DataDrop, "data.drop")
216 217 218
    CASE_OP(MemoryCopy, "memory.copy")
    CASE_OP(MemoryFill, "memory.fill")
    CASE_OP(TableInit, "table.init")
219
    CASE_OP(ElemDrop, "elem.drop")
220
    CASE_OP(TableCopy, "table.copy")
221
    CASE_OP(TableGrow, "table.grow")
222
    CASE_OP(TableSize, "table.size")
223
    CASE_OP(TableFill, "table.fill")
224

225 226 227
    // SIMD opcodes.
    CASE_SIMD_OP(Splat, "splat")
    CASE_SIMD_OP(Neg, "neg")
228
    CASE_SIMDF_OP(Sqrt, "sqrt")
229 230 231 232 233
    CASE_SIMD_OP(Eq, "eq")
    CASE_SIMD_OP(Ne, "ne")
    CASE_SIMD_OP(Add, "add")
    CASE_SIMD_OP(Sub, "sub")
    CASE_SIMD_OP(Mul, "mul")
234 235 236 237 238 239
    CASE_SIMDF_OP(Div, "div")
    CASE_SIMDF_OP(Lt, "lt")
    CASE_SIMDF_OP(Le, "le")
    CASE_SIMDF_OP(Gt, "gt")
    CASE_SIMDF_OP(Ge, "ge")
    CASE_SIMDF_OP(Abs, "abs")
240
    CASE_F32x4_OP(AddHoriz, "add_horizontal")
241
    CASE_F32x4_OP(RecipApprox, "recip_approx")
242
    CASE_F32x4_OP(RecipSqrtApprox, "recip_sqrt_approx")
243 244
    CASE_SIMDF_OP(Min, "min")
    CASE_SIMDF_OP(Max, "max")
245
    CASE_CONVERT_OP(Convert, F32x4, I32x4, "i32", "convert")
246
    CASE_CONVERT_OP(Convert, I32x4, F32x4, "f32", "convert")
247 248 249 250 251 252
    CASE_CONVERT_OP(Convert, I32x4, I16x8Low, "i32", "convert")
    CASE_CONVERT_OP(Convert, I32x4, I16x8High, "i32", "convert")
    CASE_CONVERT_OP(Convert, I16x8, I32x4, "i32", "convert")
    CASE_CONVERT_OP(Convert, I16x8, I8x16Low, "i32", "convert")
    CASE_CONVERT_OP(Convert, I16x8, I8x16High, "i32", "convert")
    CASE_CONVERT_OP(Convert, I8x16, I16x8, "i32", "convert")
253 254
    CASE_SIMDF_OP(ExtractLane, "extract_lane")
    CASE_SIMDF_OP(ReplaceLane, "replace_lane")
255 256
    CASE_I64x2_OP(ExtractLane, "extract_lane")
    CASE_I64x2_OP(ReplaceLane, "replace_lane")
257 258 259
    CASE_I32x4_OP(ExtractLane, "extract_lane")
    CASE_SIGN_OP(I16x8, ExtractLane, "extract_lane")
    CASE_SIGN_OP(I8x16, ExtractLane, "extract_lane")
260 261
    CASE_SIMDI_OP(ReplaceLane, "replace_lane")
    CASE_SIGN_OP(SIMDI, Min, "min")
262
    CASE_SIGN_OP(I64x2, Min, "min")
263
    CASE_SIGN_OP(SIMDI, Max, "max")
264
    CASE_SIGN_OP(I64x2, Max, "max")
265
    CASE_SIGN_OP(SIMDI, Lt, "lt")
266
    CASE_SIGN_OP(I64x2, Lt, "lt")
267
    CASE_SIGN_OP(SIMDI, Le, "le")
268
    CASE_SIGN_OP(I64x2, Le, "le")
269
    CASE_SIGN_OP(SIMDI, Gt, "gt")
270
    CASE_SIGN_OP(I64x2, Gt, "gt")
271
    CASE_SIGN_OP(SIMDI, Ge, "ge")
272
    CASE_SIGN_OP(I64x2, Ge, "ge")
273
    CASE_SIGN_OP(SIMDI, Shr, "shr")
274
    CASE_SIGN_OP(I64x2, Shr, "shr")
275
    CASE_SIMDI_OP(Shl, "shl")
276
    CASE_I64x2_OP(Shl, "shl")
277 278
    CASE_I32x4_OP(AddHoriz, "add_horizontal")
    CASE_I16x8_OP(AddHoriz, "add_horizontal")
279 280 281 282
    CASE_SIGN_OP(I16x8, AddSaturate, "add_saturate")
    CASE_SIGN_OP(I8x16, AddSaturate, "add_saturate")
    CASE_SIGN_OP(I16x8, SubSaturate, "sub_saturate")
    CASE_SIGN_OP(I8x16, SubSaturate, "sub_saturate")
283
    CASE_S128_OP(And, "and")
284
    CASE_S128_OP(Or, "or")
285 286
    CASE_S128_OP(Xor, "xor")
    CASE_S128_OP(Not, "not")
287
    CASE_S128_OP(Select, "select")
288
    CASE_S128_OP(AndNot, "andnot")
289
    CASE_S8x16_OP(Swizzle, "swizzle")
290
    CASE_S8x16_OP(Shuffle, "shuffle")
291 292
    CASE_S1x2_OP(AnyTrue, "any_true")
    CASE_S1x2_OP(AllTrue, "all_true")
293 294 295 296 297 298
    CASE_S1x4_OP(AnyTrue, "any_true")
    CASE_S1x4_OP(AllTrue, "all_true")
    CASE_S1x8_OP(AnyTrue, "any_true")
    CASE_S1x8_OP(AllTrue, "all_true")
    CASE_S1x16_OP(AnyTrue, "any_true")
    CASE_S1x16_OP(AllTrue, "all_true")
299 300
    CASE_SIMDF_OP(Qfma, "qfma")
    CASE_SIMDF_OP(Qfms, "qfms")
301

302 303
    CASE_S8x16_OP(LoadSplat, "load_splat")
    CASE_S16x8_OP(LoadSplat, "load_splat")
304 305
    CASE_S32x4_OP(LoadSplat, "load_splat")
    CASE_S64x2_OP(LoadSplat, "load_splat")
306 307
    CASE_I16x8_OP(Load8x8S, "load8x8_s")
    CASE_I16x8_OP(Load8x8U, "load8x8_u")
308 309 310 311
    CASE_I32x4_OP(Load16x4S, "load16x4_s")
    CASE_I32x4_OP(Load16x4U, "load16x4_u")
    CASE_I64x2_OP(Load32x2S, "load32x2_s")
    CASE_I64x2_OP(Load32x2U, "load32x2_u")
312

313 314 315
    CASE_I8x16_OP(RoundingAverageU, "avgr_u")
    CASE_I16x8_OP(RoundingAverageU, "avgr_u")

316 317 318 319
    CASE_I8x16_OP(Abs, "abs")
    CASE_I16x8_OP(Abs, "abs")
    CASE_I32x4_OP(Abs, "abs")

320
    // Atomic operations.
321 322
    CASE_OP(AtomicNotify, "atomic.notify")
    CASE_INT_OP(AtomicWait, "atomic.wait")
323
    CASE_OP(AtomicFence, "atomic.fence")
324 325 326 327 328 329 330 331 332
    CASE_UNSIGNED_ALL_OP(AtomicLoad, "atomic.load")
    CASE_UNSIGNED_ALL_OP(AtomicStore, "atomic.store")
    CASE_UNSIGNED_ALL_OP(AtomicAdd, "atomic.add")
    CASE_UNSIGNED_ALL_OP(AtomicSub, "atomic.sub")
    CASE_UNSIGNED_ALL_OP(AtomicAnd, "atomic.and")
    CASE_UNSIGNED_ALL_OP(AtomicOr, "atomic.or")
    CASE_UNSIGNED_ALL_OP(AtomicXor, "atomic.xor")
    CASE_UNSIGNED_ALL_OP(AtomicExchange, "atomic.xchng")
    CASE_UNSIGNED_ALL_OP(AtomicCompareExchange, "atomic.cmpxchng")
333 334 335

    default : return "unknown";
    // clang-format on
336 337
  }
}
338

339 340 341 342 343
#undef CASE_OP
#undef CASE_I32_OP
#undef CASE_I64_OP
#undef CASE_F32_OP
#undef CASE_F64_OP
344
#undef CASE_REF_OP
345
#undef CASE_F64x2_OP
346
#undef CASE_F32x4_OP
347
#undef CASE_I64x2_OP
348 349 350 351
#undef CASE_I32x4_OP
#undef CASE_I16x8_OP
#undef CASE_I8x16_OP
#undef CASE_S128_OP
352
#undef CASE_S64x2_OP
353 354 355
#undef CASE_S32x4_OP
#undef CASE_S16x8_OP
#undef CASE_S8x16_OP
356
#undef CASE_S1x2_OP
357 358 359 360 361 362 363 364 365 366
#undef CASE_S1x4_OP
#undef CASE_S1x8_OP
#undef CASE_S1x16_OP
#undef CASE_INT_OP
#undef CASE_FLOAT_OP
#undef CASE_ALL_OP
#undef CASE_SIMD_OP
#undef CASE_SIMDI_OP
#undef CASE_SIGN_OP
#undef CASE_UNSIGNED_OP
367
#undef CASE_UNSIGNED_ALL_OP
368 369
#undef CASE_ALL_SIGN_OP
#undef CASE_CONVERT_OP
370
#undef CASE_CONVERT_SAT_OP
371 372 373
#undef CASE_L32_OP
#undef CASE_U32_OP

374 375
bool WasmOpcodes::IsPrefixOpcode(WasmOpcode opcode) {
  switch (opcode) {
376
#define CHECK_PREFIX(name, opcode) case k##name##Prefix:
377 378
    FOREACH_PREFIX(CHECK_PREFIX)
#undef CHECK_PREFIX
379
    return true;
380 381 382 383
    default:
      return false;
  }
}
384

385 386
bool WasmOpcodes::IsControlOpcode(WasmOpcode opcode) {
  switch (opcode) {
387
#define CHECK_OPCODE(name, opcode, _) case kExpr##name:
388 389
    FOREACH_CONTROL_OPCODE(CHECK_OPCODE)
#undef CHECK_OPCODE
390
    return true;
391 392 393 394
    default:
      return false;
  }
}
395

396 397 398 399 400 401 402 403 404 405 406 407
bool WasmOpcodes::IsUnconditionalJump(WasmOpcode opcode) {
  switch (opcode) {
    case kExprUnreachable:
    case kExprBr:
    case kExprBrTable:
    case kExprReturn:
      return true;
    default:
      return false;
  }
}

408 409 410 411
bool WasmOpcodes::IsAnyRefOpcode(WasmOpcode opcode) {
  switch (opcode) {
    case kExprRefNull:
    case kExprRefIsNull:
412
    case kExprRefFunc:
413 414 415 416 417
      return true;
    default:
      return false;
  }
}
418

419 420 421 422 423 424 425 426 427 428 429 430 431
bool WasmOpcodes::IsThrowingOpcode(WasmOpcode opcode) {
  // TODO(8729): Trapping opcodes are not yet considered to be throwing.
  switch (opcode) {
    case kExprThrow:
    case kExprRethrow:
    case kExprCallFunction:
    case kExprCallIndirect:
      return true;
    default:
      return false;
  }
}

432 433 434 435 436 437 438 439 440 441 442
bool WasmOpcodes::IsSimdPostMvpOpcode(WasmOpcode opcode) {
  switch (opcode) {
#define CHECK_OPCODE(name, opcode, _) case kExpr##name:
    FOREACH_SIMD_POST_MVP_OPCODE(CHECK_OPCODE)
#undef CHECK_OPCODE
    return true;
    default:
      return false;
  }
}

443 444
std::ostream& operator<<(std::ostream& os, const FunctionSig& sig) {
  if (sig.return_count() == 0) os << "v";
445
  for (auto ret : sig.returns()) {
446
    os << ret.short_name();
447 448 449
  }
  os << "_";
  if (sig.parameter_count() == 0) os << "v";
450
  for (auto param : sig.parameters()) {
451
    os << param.short_name();
452 453 454 455
  }
  return os;
}

456 457
bool IsJSCompatibleSignature(const FunctionSig* sig,
                             const WasmFeatures& enabled_features) {
458
  if (!enabled_features.has_mv() && sig->return_count() > 1) {
459 460
    return false;
  }
461
  for (auto type : sig->all()) {
462
    if (!enabled_features.has_bigint() && type == kWasmI64) {
463 464 465 466
      return false;
    }

    if (type == kWasmS128) return false;
467
  }
468
  return true;
469 470
}

471 472
namespace {

473
#define DECLARE_SIG_ENUM(name, ...) kSigEnum_##name,
474 475 476 477
enum WasmOpcodeSig : byte {
  kSigEnum_None,
  FOREACH_SIGNATURE(DECLARE_SIG_ENUM)
};
478
#undef DECLARE_SIG_ENUM
479 480 481 482 483 484
#define DECLARE_SIG(name, ...)                                                \
  constexpr ValueType kTypes_##name[] = {__VA_ARGS__};                        \
  constexpr int kReturnsCount_##name = kTypes_##name[0] == kWasmStmt ? 0 : 1; \
  constexpr FunctionSig kSig_##name(                                          \
      kReturnsCount_##name, static_cast<int>(arraysize(kTypes_##name)) - 1,   \
      kTypes_##name + (1 - kReturnsCount_##name));
485
FOREACH_SIGNATURE(DECLARE_SIG)
486
#undef DECLARE_SIG
487 488

#define DECLARE_SIG_ENTRY(name, ...) &kSig_##name,
489
constexpr const FunctionSig* kCachedSigs[] = {
490
    nullptr, FOREACH_SIGNATURE(DECLARE_SIG_ENTRY)};
491
#undef DECLARE_SIG_ENTRY
492

493
constexpr WasmOpcodeSig GetShortOpcodeSigIndex(byte opcode) {
494
#define CASE(name, opc, sig) opcode == opc ? kSigEnum_##sig:
495 496
    return FOREACH_SIMPLE_OPCODE(CASE) FOREACH_SIMPLE_PROTOTYPE_OPCODE(CASE)
        kSigEnum_None;
497
#undef CASE
498
}
499

500
constexpr WasmOpcodeSig GetAsmJsOpcodeSigIndex(byte opcode) {
501
#define CASE(name, opc, sig) opcode == opc ? kSigEnum_##sig:
502
    return FOREACH_ASMJS_COMPAT_OPCODE(CASE) kSigEnum_None;
503
#undef CASE
504
}
505

506
constexpr WasmOpcodeSig GetSimdOpcodeSigIndex(byte opcode) {
507
#define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
508 509
    return FOREACH_SIMD_0_OPERAND_OPCODE(CASE) FOREACH_SIMD_MEM_OPCODE(CASE)
        kSigEnum_None;
510
#undef CASE
511
}
512

513
constexpr WasmOpcodeSig GetAtomicOpcodeSigIndex(byte opcode) {
514
#define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
515 516
    return FOREACH_ATOMIC_OPCODE(CASE) FOREACH_ATOMIC_0_OPERAND_OPCODE(CASE)
        kSigEnum_None;
517 518
#undef CASE
}
519

520
constexpr WasmOpcodeSig GetNumericOpcodeSigIndex(byte opcode) {
521 522 523
#define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
    return FOREACH_NUMERIC_OPCODE(CASE) kSigEnum_None;
#undef CASE
524
}
525

526
constexpr std::array<WasmOpcodeSig, 256> kShortSigTable =
527
    base::make_array<256>(GetShortOpcodeSigIndex);
528
constexpr std::array<WasmOpcodeSig, 256> kSimpleAsmjsExprSigTable =
529
    base::make_array<256>(GetAsmJsOpcodeSigIndex);
530
constexpr std::array<WasmOpcodeSig, 256> kSimdExprSigTable =
531
    base::make_array<256>(GetSimdOpcodeSigIndex);
532
constexpr std::array<WasmOpcodeSig, 256> kAtomicExprSigTable =
533
    base::make_array<256>(GetAtomicOpcodeSigIndex);
534
constexpr std::array<WasmOpcodeSig, 256> kNumericExprSigTable =
535
    base::make_array<256>(GetNumericOpcodeSigIndex);
536

537
}  // namespace
538

539
const FunctionSig* WasmOpcodes::Signature(WasmOpcode opcode) {
540
  switch (opcode >> 8) {
541
    case 0:
542
      return kCachedSigs[kShortSigTable[opcode]];
543
    case kSimdPrefix:
544
      return kCachedSigs[kSimdExprSigTable[opcode & 0xFF]];
545
    case kAtomicPrefix:
546
      return kCachedSigs[kAtomicExprSigTable[opcode & 0xFF]];
547
    case kNumericPrefix:
548
      return kCachedSigs[kNumericExprSigTable[opcode & 0xFF]];
549
    default:
550 551
      UNREACHABLE();  // invalid prefix.
      return nullptr;
552
  }
553 554
}

555
const FunctionSig* WasmOpcodes::AsmjsSignature(WasmOpcode opcode) {
556
  DCHECK_GT(kSimpleAsmjsExprSigTable.size(), opcode);
557
  return kCachedSigs[kSimpleAsmjsExprSigTable[opcode]];
558 559
}

560 561 562 563 564 565 566 567
// Define constexpr arrays.
constexpr uint8_t LoadType::kLoadSizeLog2[];
constexpr ValueType LoadType::kValueType[];
constexpr MachineType LoadType::kMemType[];
constexpr uint8_t StoreType::kStoreSizeLog2[];
constexpr ValueType StoreType::kValueType[];
constexpr MachineRepresentation StoreType::kMemRep[];

568
MessageTemplate WasmOpcodes::TrapReasonToMessageId(TrapReason reason) {
569 570 571 572 573 574 575 576 577 578 579 580
  switch (reason) {
#define TRAPREASON_TO_MESSAGE(name) \
  case k##name:                     \
    return MessageTemplate::kWasm##name;
    FOREACH_WASM_TRAPREASON(TRAPREASON_TO_MESSAGE)
#undef TRAPREASON_TO_MESSAGE
    default:
      return MessageTemplate::kNone;
  }
}

const char* WasmOpcodes::TrapReasonMessage(TrapReason reason) {
581
  return MessageFormatter::TemplateString(TrapReasonToMessageId(reason));
582
}
583 584 585
}  // namespace wasm
}  // namespace internal
}  // namespace v8