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