5 #include "src/wasm/wasm-opcodes.h" 9 #include "src/base/template-utils.h" 10 #include "src/messages.h" 11 #include "src/runtime/runtime.h" 12 #include "src/signature.h" 18 #define CASE_OP(name, 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") 71 const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
76 CASE_INT_OP(Eqz,
"eqz")
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")
129 CASE_OP(Block, "block")
130 CASE_OP(Loop, "loop")
132 CASE_OP(Else, "else")
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")
163 CASE_OP(Throw, "throw")
164 CASE_OP(Rethrow, "rethrow")
165 CASE_OP(Catch, "catch")
166 CASE_OP(CatchAll, "catch_all")
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")
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")
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")
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")
278 default : return "unknown";
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 314 bool WasmOpcodes::IsPrefixOpcode(WasmOpcode opcode) {
316 #define CHECK_PREFIX(name, opcode) case k##name##Prefix: 317 FOREACH_PREFIX(CHECK_PREFIX)
325 bool WasmOpcodes::IsControlOpcode(WasmOpcode opcode) {
327 #define CHECK_OPCODE(name, opcode, _) case kExpr##name: 328 FOREACH_CONTROL_OPCODE(CHECK_OPCODE)
336 bool WasmOpcodes::IsUnconditionalJump(WasmOpcode opcode) {
338 case kExprUnreachable:
348 bool WasmOpcodes::IsSignExtensionOpcode(WasmOpcode opcode) {
350 case kExprI32SExtendI8:
351 case kExprI32SExtendI16:
352 case kExprI64SExtendI8:
353 case kExprI64SExtendI16:
354 case kExprI64SExtendI32:
361 bool WasmOpcodes::IsAnyRefOpcode(WasmOpcode opcode) {
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);
377 if (sig.parameter_count() == 0) os <<
"v";
378 for (
auto param : sig.parameters()) {
379 os << ValueTypes::ShortNameOf(param);
384 bool IsJSCompatibleSignature(
const FunctionSig* sig) {
385 for (
auto type : sig->all()) {
386 if (type == kWasmI64 || type == kWasmS128)
return false;
388 return sig->return_count() <= 1;
393 #define DECLARE_SIG_ENUM(name, ...) kSigEnum_##name, 394 enum WasmOpcodeSig : byte {
396 FOREACH_SIGNATURE(DECLARE_SIG_ENUM)
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)
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 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)
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;
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)
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;
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;
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{});
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;
482 const std::array<const FunctionSig*, 256> kSimpleOpcodeSigs =
483 base::make_array<256>(GetSimpleOpcodeSig{});
485 FunctionSig* WasmOpcodes::Signature(WasmOpcode opcode) {
486 switch (opcode >> 8) {
488 return const_cast<FunctionSig*
>(kCachedSigs[kShortSigTable[opcode]]);
490 return const_cast<FunctionSig*
>(
491 kCachedSigs[kSimdExprSigTable[opcode & 0xFF]]);
493 return const_cast<FunctionSig*
>(
494 kCachedSigs[kAtomicExprSigTable[opcode & 0xFF]]);
496 return const_cast<FunctionSig*
>(
497 kCachedSigs[kNumericExprSigTable[opcode & 0xFF]]);
504 FunctionSig* WasmOpcodes::AsmjsSignature(WasmOpcode opcode) {
505 DCHECK_GT(kSimpleAsmjsExprSigTable.size(), opcode);
506 return const_cast<FunctionSig*
>(
507 kCachedSigs[kSimpleAsmjsExprSigTable[opcode]]);
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[];
518 MessageTemplate WasmOpcodes::TrapReasonToMessageId(TrapReason reason) {
520 #define TRAPREASON_TO_MESSAGE(name) \ 522 return MessageTemplate::kWasm##name; 523 FOREACH_WASM_TRAPREASON(TRAPREASON_TO_MESSAGE)
524 #undef TRAPREASON_TO_MESSAGE 526 return MessageTemplate::kNone;
530 const char* WasmOpcodes::TrapReasonMessage(TrapReason reason) {
531 return MessageFormatter::TemplateString(TrapReasonToMessageId(reason));