V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
wasm-opcodes.cc
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 #include "src/wasm/wasm-opcodes.h"
6 
7 #include <array>
8 
9 #include "src/base/template-utils.h"
10 #include "src/messages.h"
11 #include "src/runtime/runtime.h"
12 #include "src/signature.h"
13 
14 namespace v8 {
15 namespace internal {
16 namespace wasm {
17 
18 #define CASE_OP(name, str) \
19  case kExpr##name: \
20  return str;
21 #define CASE_I32_OP(name, str) CASE_OP(I32##name, "i32." str)
22 #define CASE_I64_OP(name, str) CASE_OP(I64##name, "i64." str)
23 #define CASE_F32_OP(name, str) CASE_OP(F32##name, "f32." str)
24 #define CASE_F64_OP(name, str) CASE_OP(F64##name, "f64." str)
25 #define CASE_REF_OP(name, str) CASE_OP(Ref##name, "ref." str)
26 #define CASE_F32x4_OP(name, str) CASE_OP(F32x4##name, "f32x4." str)
27 #define CASE_I32x4_OP(name, str) CASE_OP(I32x4##name, "i32x4." str)
28 #define CASE_I16x8_OP(name, str) CASE_OP(I16x8##name, "i16x8." str)
29 #define CASE_I8x16_OP(name, str) CASE_OP(I8x16##name, "i8x16." str)
30 #define CASE_S128_OP(name, str) CASE_OP(S128##name, "s128." str)
31 #define CASE_S32x4_OP(name, str) CASE_OP(S32x4##name, "s32x4." str)
32 #define CASE_S16x8_OP(name, str) CASE_OP(S16x8##name, "s16x8." str)
33 #define CASE_S8x16_OP(name, str) CASE_OP(S8x16##name, "s8x16." str)
34 #define CASE_S1x4_OP(name, str) CASE_OP(S1x4##name, "s1x4." str)
35 #define CASE_S1x8_OP(name, str) CASE_OP(S1x8##name, "s1x8." str)
36 #define CASE_S1x16_OP(name, str) CASE_OP(S1x16##name, "s1x16." str)
37 #define CASE_INT_OP(name, str) CASE_I32_OP(name, str) CASE_I64_OP(name, str)
38 #define CASE_FLOAT_OP(name, str) CASE_F32_OP(name, str) CASE_F64_OP(name, str)
39 #define CASE_ALL_OP(name, str) CASE_FLOAT_OP(name, str) CASE_INT_OP(name, str)
40 #define CASE_SIMD_OP(name, str) \
41  CASE_F32x4_OP(name, str) CASE_I32x4_OP(name, str) CASE_I16x8_OP(name, str) \
42  CASE_I8x16_OP(name, str)
43 #define CASE_SIMDI_OP(name, str) \
44  CASE_I32x4_OP(name, str) CASE_I16x8_OP(name, str) CASE_I8x16_OP(name, str)
45 #define CASE_SIGN_OP(TYPE, name, str) \
46  CASE_##TYPE##_OP(name##S, str "_s") CASE_##TYPE##_OP(name##U, str "_u")
47 #define CASE_UNSIGNED_OP(TYPE, name, str) CASE_##TYPE##_OP(name##U, str "_u")
48 #define CASE_ALL_SIGN_OP(name, str) \
49  CASE_FLOAT_OP(name, str) CASE_SIGN_OP(INT, name, str)
50 #define CASE_CONVERT_OP(name, RES, SRC, src_suffix, str) \
51  CASE_##RES##_OP(U##name##SRC, str "_u/" src_suffix) \
52  CASE_##RES##_OP(S##name##SRC, str "_s/" src_suffix)
53 #define CASE_CONVERT_SAT_OP(name, RES, SRC, src_suffix, str) \
54  CASE_##RES##_OP(U##name##Sat##SRC, str "_u:sat/" src_suffix) \
55  CASE_##RES##_OP(S##name##Sat##SRC, str "_s:sat/" src_suffix)
56 #define CASE_L32_OP(name, str) \
57  CASE_SIGN_OP(I32, name##8, str "8") \
58  CASE_SIGN_OP(I32, name##16, str "16") \
59  CASE_I32_OP(name, str "32")
60 #define CASE_U32_OP(name, str) \
61  CASE_I32_OP(name, str "32") \
62  CASE_UNSIGNED_OP(I32, name##8, str "8") \
63  CASE_UNSIGNED_OP(I32, name##16, str "16")
64 #define CASE_UNSIGNED_ALL_OP(name, str) \
65  CASE_U32_OP(name, str) \
66  CASE_I64_OP(name, str "64") \
67  CASE_UNSIGNED_OP(I64, name##8, str "8") \
68  CASE_UNSIGNED_OP(I64, name##16, str "16") \
69  CASE_UNSIGNED_OP(I64, name##32, str "32")
70 
71 const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
72  switch (opcode) {
73  // clang-format off
74 
75  // Standard opcodes
76  CASE_INT_OP(Eqz, "eqz")
77  CASE_ALL_OP(Eq, "eq")
78  CASE_ALL_OP(Ne, "ne")
79  CASE_ALL_OP(Add, "add")
80  CASE_ALL_OP(Sub, "sub")
81  CASE_ALL_OP(Mul, "mul")
82  CASE_ALL_SIGN_OP(Lt, "lt")
83  CASE_ALL_SIGN_OP(Gt, "gt")
84  CASE_ALL_SIGN_OP(Le, "le")
85  CASE_ALL_SIGN_OP(Ge, "ge")
86  CASE_INT_OP(Clz, "clz")
87  CASE_INT_OP(Ctz, "ctz")
88  CASE_INT_OP(Popcnt, "popcnt")
89  CASE_ALL_SIGN_OP(Div, "div")
90  CASE_SIGN_OP(INT, Rem, "rem")
91  CASE_INT_OP(And, "and")
92  CASE_INT_OP(Ior, "or")
93  CASE_INT_OP(Xor, "xor")
94  CASE_INT_OP(Shl, "shl")
95  CASE_SIGN_OP(INT, Shr, "shr")
96  CASE_INT_OP(Rol, "rol")
97  CASE_INT_OP(Ror, "ror")
98  CASE_FLOAT_OP(Abs, "abs")
99  CASE_FLOAT_OP(Neg, "neg")
100  CASE_FLOAT_OP(Ceil, "ceil")
101  CASE_FLOAT_OP(Floor, "floor")
102  CASE_FLOAT_OP(Trunc, "trunc")
103  CASE_FLOAT_OP(NearestInt, "nearest")
104  CASE_FLOAT_OP(Sqrt, "sqrt")
105  CASE_FLOAT_OP(Min, "min")
106  CASE_FLOAT_OP(Max, "max")
107  CASE_FLOAT_OP(CopySign, "copysign")
108  CASE_REF_OP(Null, "null")
109  CASE_REF_OP(IsNull, "is_null")
110  CASE_I32_OP(ConvertI64, "wrap/i64")
111  CASE_CONVERT_OP(Convert, INT, F32, "f32", "trunc")
112  CASE_CONVERT_OP(Convert, INT, F64, "f64", "trunc")
113  CASE_CONVERT_OP(Convert, I64, I32, "i32", "extend")
114  CASE_CONVERT_OP(Convert, F32, I32, "i32", "convert")
115  CASE_CONVERT_OP(Convert, F32, I64, "i64", "convert")
116  CASE_F32_OP(ConvertF64, "demote/f64")
117  CASE_CONVERT_OP(Convert, F64, I32, "i32", "convert")
118  CASE_CONVERT_OP(Convert, F64, I64, "i64", "convert")
119  CASE_F64_OP(ConvertF32, "promote/f32")
120  CASE_I32_OP(ReinterpretF32, "reinterpret/f32")
121  CASE_I64_OP(ReinterpretF64, "reinterpret/f64")
122  CASE_F32_OP(ReinterpretI32, "reinterpret/i32")
123  CASE_F64_OP(ReinterpretI64, "reinterpret/i64")
124  CASE_INT_OP(SExtendI8, "sign_extend8")
125  CASE_INT_OP(SExtendI16, "sign_extend16")
126  CASE_I64_OP(SExtendI32, "sign_extend32")
127  CASE_OP(Unreachable, "unreachable")
128  CASE_OP(Nop, "nop")
129  CASE_OP(Block, "block")
130  CASE_OP(Loop, "loop")
131  CASE_OP(If, "if")
132  CASE_OP(Else, "else")
133  CASE_OP(End, "end")
134  CASE_OP(Br, "br")
135  CASE_OP(BrIf, "br_if")
136  CASE_OP(BrTable, "br_table")
137  CASE_OP(Return, "return")
138  CASE_OP(CallFunction, "call")
139  CASE_OP(CallIndirect, "call_indirect")
140  CASE_OP(Drop, "drop")
141  CASE_OP(Select, "select")
142  CASE_OP(GetLocal, "get_local")
143  CASE_OP(SetLocal, "set_local")
144  CASE_OP(TeeLocal, "tee_local")
145  CASE_OP(GetGlobal, "get_global")
146  CASE_OP(SetGlobal, "set_global")
147  CASE_ALL_OP(Const, "const")
148  CASE_OP(MemorySize, "memory.size")
149  CASE_OP(MemoryGrow, "memory.grow")
150  CASE_ALL_OP(LoadMem, "load")
151  CASE_SIGN_OP(INT, LoadMem8, "load8")
152  CASE_SIGN_OP(INT, LoadMem16, "load16")
153  CASE_SIGN_OP(I64, LoadMem32, "load32")
154  CASE_S128_OP(LoadMem, "load128")
155  CASE_ALL_OP(StoreMem, "store")
156  CASE_INT_OP(StoreMem8, "store8")
157  CASE_INT_OP(StoreMem16, "store16")
158  CASE_I64_OP(StoreMem32, "store32")
159  CASE_S128_OP(StoreMem, "store128")
160 
161  // Non-standard opcodes.
162  CASE_OP(Try, "try")
163  CASE_OP(Throw, "throw")
164  CASE_OP(Rethrow, "rethrow")
165  CASE_OP(Catch, "catch")
166  CASE_OP(CatchAll, "catch_all")
167 
168  // asm.js-only opcodes.
169  CASE_F64_OP(Acos, "acos")
170  CASE_F64_OP(Asin, "asin")
171  CASE_F64_OP(Atan, "atan")
172  CASE_F64_OP(Cos, "cos")
173  CASE_F64_OP(Sin, "sin")
174  CASE_F64_OP(Tan, "tan")
175  CASE_F64_OP(Exp, "exp")
176  CASE_F64_OP(Log, "log")
177  CASE_F64_OP(Atan2, "atan2")
178  CASE_F64_OP(Pow, "pow")
179  CASE_F64_OP(Mod, "mod")
180  CASE_F32_OP(AsmjsLoadMem, "asmjs_load")
181  CASE_F64_OP(AsmjsLoadMem, "asmjs_load")
182  CASE_L32_OP(AsmjsLoadMem, "asmjs_load")
183  CASE_I32_OP(AsmjsStoreMem, "asmjs_store")
184  CASE_F32_OP(AsmjsStoreMem, "asmjs_store")
185  CASE_F64_OP(AsmjsStoreMem, "asmjs_store")
186  CASE_I32_OP(AsmjsStoreMem8, "asmjs_store8")
187  CASE_I32_OP(AsmjsStoreMem16, "asmjs_store16")
188  CASE_SIGN_OP(I32, AsmjsDiv, "asmjs_div")
189  CASE_SIGN_OP(I32, AsmjsRem, "asmjs_rem")
190  CASE_I32_OP(AsmjsSConvertF32, "asmjs_convert_s/f32")
191  CASE_I32_OP(AsmjsUConvertF32, "asmjs_convert_u/f32")
192  CASE_I32_OP(AsmjsSConvertF64, "asmjs_convert_s/f64")
193  CASE_I32_OP(AsmjsUConvertF64, "asmjs_convert_u/f64")
194 
195  // Numeric Opcodes.
196  CASE_CONVERT_SAT_OP(Convert, I32, F32, "f32", "trunc")
197  CASE_CONVERT_SAT_OP(Convert, I32, F64, "f64", "trunc")
198  CASE_CONVERT_SAT_OP(Convert, I64, F32, "f32", "trunc")
199  CASE_CONVERT_SAT_OP(Convert, I64, F64, "f64", "trunc")
200  CASE_OP(MemoryInit, "memory.init")
201  CASE_OP(MemoryDrop, "memory.drop")
202  CASE_OP(MemoryCopy, "memory.copy")
203  CASE_OP(MemoryFill, "memory.fill")
204  CASE_OP(TableInit, "table.init")
205  CASE_OP(TableDrop, "table.drop")
206  CASE_OP(TableCopy, "table.copy")
207 
208  // SIMD opcodes.
209  CASE_SIMD_OP(Splat, "splat")
210  CASE_SIMD_OP(Neg, "neg")
211  CASE_SIMD_OP(Eq, "eq")
212  CASE_SIMD_OP(Ne, "ne")
213  CASE_SIMD_OP(Add, "add")
214  CASE_SIMD_OP(Sub, "sub")
215  CASE_SIMD_OP(Mul, "mul")
216  CASE_F32x4_OP(Abs, "abs")
217  CASE_F32x4_OP(AddHoriz, "add_horizontal")
218  CASE_F32x4_OP(RecipApprox, "recip_approx")
219  CASE_F32x4_OP(RecipSqrtApprox, "recip_sqrt_approx")
220  CASE_F32x4_OP(Min, "min")
221  CASE_F32x4_OP(Max, "max")
222  CASE_F32x4_OP(Lt, "lt")
223  CASE_F32x4_OP(Le, "le")
224  CASE_F32x4_OP(Gt, "gt")
225  CASE_F32x4_OP(Ge, "ge")
226  CASE_CONVERT_OP(Convert, F32x4, I32x4, "i32", "convert")
227  CASE_CONVERT_OP(Convert, I32x4, F32x4, "f32", "convert")
228  CASE_CONVERT_OP(Convert, I32x4, I16x8Low, "i32", "convert")
229  CASE_CONVERT_OP(Convert, I32x4, I16x8High, "i32", "convert")
230  CASE_CONVERT_OP(Convert, I16x8, I32x4, "i32", "convert")
231  CASE_CONVERT_OP(Convert, I16x8, I8x16Low, "i32", "convert")
232  CASE_CONVERT_OP(Convert, I16x8, I8x16High, "i32", "convert")
233  CASE_CONVERT_OP(Convert, I8x16, I16x8, "i32", "convert")
234  CASE_F32x4_OP(ExtractLane, "extract_lane")
235  CASE_F32x4_OP(ReplaceLane, "replace_lane")
236  CASE_SIMDI_OP(ExtractLane, "extract_lane")
237  CASE_SIMDI_OP(ReplaceLane, "replace_lane")
238  CASE_SIGN_OP(SIMDI, Min, "min")
239  CASE_SIGN_OP(SIMDI, Max, "max")
240  CASE_SIGN_OP(SIMDI, Lt, "lt")
241  CASE_SIGN_OP(SIMDI, Le, "le")
242  CASE_SIGN_OP(SIMDI, Gt, "gt")
243  CASE_SIGN_OP(SIMDI, Ge, "ge")
244  CASE_SIGN_OP(SIMDI, Shr, "shr")
245  CASE_SIMDI_OP(Shl, "shl")
246  CASE_I32x4_OP(AddHoriz, "add_horizontal")
247  CASE_I16x8_OP(AddHoriz, "add_horizontal")
248  CASE_SIGN_OP(I16x8, AddSaturate, "add_saturate")
249  CASE_SIGN_OP(I8x16, AddSaturate, "add_saturate")
250  CASE_SIGN_OP(I16x8, SubSaturate, "sub_saturate")
251  CASE_SIGN_OP(I8x16, SubSaturate, "sub_saturate")
252  CASE_S128_OP(And, "and")
253  CASE_S128_OP(Or, "or")
254  CASE_S128_OP(Xor, "xor")
255  CASE_S128_OP(Not, "not")
256  CASE_S128_OP(Select, "select")
257  CASE_S8x16_OP(Shuffle, "shuffle")
258  CASE_S1x4_OP(AnyTrue, "any_true")
259  CASE_S1x4_OP(AllTrue, "all_true")
260  CASE_S1x8_OP(AnyTrue, "any_true")
261  CASE_S1x8_OP(AllTrue, "all_true")
262  CASE_S1x16_OP(AnyTrue, "any_true")
263  CASE_S1x16_OP(AllTrue, "all_true")
264 
265  // Atomic operations.
266  CASE_OP(AtomicWake, "atomic_wake")
267  CASE_I32_OP(AtomicWait, "atomic_wait")
268  CASE_UNSIGNED_ALL_OP(AtomicLoad, "atomic_load")
269  CASE_UNSIGNED_ALL_OP(AtomicStore, "atomic_store")
270  CASE_UNSIGNED_ALL_OP(AtomicAdd, "atomic_add")
271  CASE_UNSIGNED_ALL_OP(AtomicSub, "atomic_sub")
272  CASE_UNSIGNED_ALL_OP(AtomicAnd, "atomic_and")
273  CASE_UNSIGNED_ALL_OP(AtomicOr, "atomic_or")
274  CASE_UNSIGNED_ALL_OP(AtomicXor, "atomic_xor")
275  CASE_UNSIGNED_ALL_OP(AtomicExchange, "atomic_xchng")
276  CASE_UNSIGNED_ALL_OP(AtomicCompareExchange, "atomic_cmpxchng")
277 
278  default : return "unknown";
279  // clang-format on
280  }
281 }
282 
283 #undef CASE_OP
284 #undef CASE_I32_OP
285 #undef CASE_I64_OP
286 #undef CASE_F32_OP
287 #undef CASE_F64_OP
288 #undef CASE_REF_OP
289 #undef CASE_F32x4_OP
290 #undef CASE_I32x4_OP
291 #undef CASE_I16x8_OP
292 #undef CASE_I8x16_OP
293 #undef CASE_S128_OP
294 #undef CASE_S32x4_OP
295 #undef CASE_S16x8_OP
296 #undef CASE_S8x16_OP
297 #undef CASE_S1x4_OP
298 #undef CASE_S1x8_OP
299 #undef CASE_S1x16_OP
300 #undef CASE_INT_OP
301 #undef CASE_FLOAT_OP
302 #undef CASE_ALL_OP
303 #undef CASE_SIMD_OP
304 #undef CASE_SIMDI_OP
305 #undef CASE_SIGN_OP
306 #undef CASE_UNSIGNED_OP
307 #undef CASE_UNSIGNED_ALL_OP
308 #undef CASE_ALL_SIGN_OP
309 #undef CASE_CONVERT_OP
310 #undef CASE_CONVERT_SAT_OP
311 #undef CASE_L32_OP
312 #undef CASE_U32_OP
313 
314 bool WasmOpcodes::IsPrefixOpcode(WasmOpcode opcode) {
315  switch (opcode) {
316 #define CHECK_PREFIX(name, opcode) case k##name##Prefix:
317  FOREACH_PREFIX(CHECK_PREFIX)
318 #undef CHECK_PREFIX
319  return true;
320  default:
321  return false;
322  }
323 }
324 
325 bool WasmOpcodes::IsControlOpcode(WasmOpcode opcode) {
326  switch (opcode) {
327 #define CHECK_OPCODE(name, opcode, _) case kExpr##name:
328  FOREACH_CONTROL_OPCODE(CHECK_OPCODE)
329 #undef CHECK_OPCODE
330  return true;
331  default:
332  return false;
333  }
334 }
335 
336 bool WasmOpcodes::IsUnconditionalJump(WasmOpcode opcode) {
337  switch (opcode) {
338  case kExprUnreachable:
339  case kExprBr:
340  case kExprBrTable:
341  case kExprReturn:
342  return true;
343  default:
344  return false;
345  }
346 }
347 
348 bool WasmOpcodes::IsSignExtensionOpcode(WasmOpcode opcode) {
349  switch (opcode) {
350  case kExprI32SExtendI8:
351  case kExprI32SExtendI16:
352  case kExprI64SExtendI8:
353  case kExprI64SExtendI16:
354  case kExprI64SExtendI32:
355  return true;
356  default:
357  return false;
358  }
359 }
360 
361 bool WasmOpcodes::IsAnyRefOpcode(WasmOpcode opcode) {
362  switch (opcode) {
363  case kExprRefNull:
364  case kExprRefIsNull:
365  return true;
366  default:
367  return false;
368  }
369 }
370 
371 std::ostream& operator<<(std::ostream& os, const FunctionSig& sig) {
372  if (sig.return_count() == 0) os << "v";
373  for (auto ret : sig.returns()) {
374  os << ValueTypes::ShortNameOf(ret);
375  }
376  os << "_";
377  if (sig.parameter_count() == 0) os << "v";
378  for (auto param : sig.parameters()) {
379  os << ValueTypes::ShortNameOf(param);
380  }
381  return os;
382 }
383 
384 bool IsJSCompatibleSignature(const FunctionSig* sig) {
385  for (auto type : sig->all()) {
386  if (type == kWasmI64 || type == kWasmS128) return false;
387  }
388  return sig->return_count() <= 1;
389 }
390 
391 namespace {
392 
393 #define DECLARE_SIG_ENUM(name, ...) kSigEnum_##name,
394 enum WasmOpcodeSig : byte {
395  kSigEnum_None,
396  FOREACH_SIGNATURE(DECLARE_SIG_ENUM)
397 };
398 #undef DECLARE_SIG_ENUM
399 #define DECLARE_SIG(name, ...) \
400  constexpr ValueType kTypes_##name[] = {__VA_ARGS__}; \
401  constexpr int kReturnsCount_##name = kTypes_##name[0] == kWasmStmt ? 0 : 1; \
402  constexpr FunctionSig kSig_##name( \
403  kReturnsCount_##name, static_cast<int>(arraysize(kTypes_##name)) - 1, \
404  kTypes_##name + (1 - kReturnsCount_##name));
405 FOREACH_SIGNATURE(DECLARE_SIG)
406 #undef DECLARE_SIG
407 
408 #define DECLARE_SIG_ENTRY(name, ...) &kSig_##name,
409 constexpr const FunctionSig* kCachedSigs[] = {
410  nullptr, FOREACH_SIGNATURE(DECLARE_SIG_ENTRY)};
411 #undef DECLARE_SIG_ENTRY
412 
413 // gcc 4.7 - 4.9 has a bug which causes the constexpr attribute to get lost when
414 // passing functions (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52892). Hence
415 // encapsulate these constexpr functions in functors.
416 // TODO(clemensh): Remove this once we require gcc >= 5.0.
417 
418 struct GetShortOpcodeSigIndex {
419  constexpr WasmOpcodeSig operator()(byte opcode) const {
420 #define CASE(name, opc, sig) opcode == opc ? kSigEnum_##sig:
421  return FOREACH_SIMPLE_OPCODE(CASE) FOREACH_SIMPLE_PROTOTYPE_OPCODE(CASE)
422  kSigEnum_None;
423 #undef CASE
424  }
425 };
426 
427 struct GetAsmJsOpcodeSigIndex {
428  constexpr WasmOpcodeSig operator()(byte opcode) const {
429 #define CASE(name, opc, sig) opcode == opc ? kSigEnum_##sig:
430  return FOREACH_ASMJS_COMPAT_OPCODE(CASE) kSigEnum_None;
431 #undef CASE
432  }
433 };
434 
435 struct GetSimdOpcodeSigIndex {
436  constexpr WasmOpcodeSig operator()(byte opcode) const {
437 #define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
438  return FOREACH_SIMD_0_OPERAND_OPCODE(CASE) FOREACH_SIMD_MEM_OPCODE(CASE)
439  kSigEnum_None;
440 #undef CASE
441  }
442 };
443 
444 struct GetAtomicOpcodeSigIndex {
445  constexpr WasmOpcodeSig operator()(byte opcode) const {
446 #define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
447  return FOREACH_ATOMIC_OPCODE(CASE) kSigEnum_None;
448 #undef CASE
449 }
450 };
451 
452 struct GetNumericOpcodeSigIndex {
453  constexpr WasmOpcodeSig operator()(byte opcode) const {
454 #define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
455  return FOREACH_NUMERIC_OPCODE(CASE) kSigEnum_None;
456 #undef CASE
457  }
458 };
459 
460 constexpr std::array<WasmOpcodeSig, 256> kShortSigTable =
461  base::make_array<256>(GetShortOpcodeSigIndex{});
462 constexpr std::array<WasmOpcodeSig, 256> kSimpleAsmjsExprSigTable =
463  base::make_array<256>(GetAsmJsOpcodeSigIndex{});
464 constexpr std::array<WasmOpcodeSig, 256> kSimdExprSigTable =
465  base::make_array<256>(GetSimdOpcodeSigIndex{});
466 constexpr std::array<WasmOpcodeSig, 256> kAtomicExprSigTable =
467  base::make_array<256>(GetAtomicOpcodeSigIndex{});
468 constexpr std::array<WasmOpcodeSig, 256> kNumericExprSigTable =
469  base::make_array<256>(GetNumericOpcodeSigIndex{});
470 
471 // Computes a direct pointer to a cached signature for a simple opcode.
472 struct GetSimpleOpcodeSig {
473  constexpr const FunctionSig* operator()(byte opcode) const {
474 #define CASE(name, opc, sig) opcode == opc ? &kSig_##sig:
475  return FOREACH_SIMPLE_OPCODE(CASE) nullptr;
476 #undef CASE
477  }
478 };
479 
480 } // namespace
481 
482 const std::array<const FunctionSig*, 256> kSimpleOpcodeSigs =
483  base::make_array<256>(GetSimpleOpcodeSig{});
484 
485 FunctionSig* WasmOpcodes::Signature(WasmOpcode opcode) {
486  switch (opcode >> 8) {
487  case 0:
488  return const_cast<FunctionSig*>(kCachedSigs[kShortSigTable[opcode]]);
489  case kSimdPrefix:
490  return const_cast<FunctionSig*>(
491  kCachedSigs[kSimdExprSigTable[opcode & 0xFF]]);
492  case kAtomicPrefix:
493  return const_cast<FunctionSig*>(
494  kCachedSigs[kAtomicExprSigTable[opcode & 0xFF]]);
495  case kNumericPrefix:
496  return const_cast<FunctionSig*>(
497  kCachedSigs[kNumericExprSigTable[opcode & 0xFF]]);
498  default:
499  UNREACHABLE(); // invalid prefix.
500  return nullptr;
501  }
502 }
503 
504 FunctionSig* WasmOpcodes::AsmjsSignature(WasmOpcode opcode) {
505  DCHECK_GT(kSimpleAsmjsExprSigTable.size(), opcode);
506  return const_cast<FunctionSig*>(
507  kCachedSigs[kSimpleAsmjsExprSigTable[opcode]]);
508 }
509 
510 // Define constexpr arrays.
511 constexpr uint8_t LoadType::kLoadSizeLog2[];
512 constexpr ValueType LoadType::kValueType[];
513 constexpr MachineType LoadType::kMemType[];
514 constexpr uint8_t StoreType::kStoreSizeLog2[];
515 constexpr ValueType StoreType::kValueType[];
516 constexpr MachineRepresentation StoreType::kMemRep[];
517 
518 MessageTemplate WasmOpcodes::TrapReasonToMessageId(TrapReason reason) {
519  switch (reason) {
520 #define TRAPREASON_TO_MESSAGE(name) \
521  case k##name: \
522  return MessageTemplate::kWasm##name;
523  FOREACH_WASM_TRAPREASON(TRAPREASON_TO_MESSAGE)
524 #undef TRAPREASON_TO_MESSAGE
525  default:
526  return MessageTemplate::kNone;
527  }
528 }
529 
530 const char* WasmOpcodes::TrapReasonMessage(TrapReason reason) {
531  return MessageFormatter::TemplateString(TrapReasonToMessageId(reason));
532 }
533 } // namespace wasm
534 } // namespace internal
535 } // namespace v8
Definition: libplatform.h:13