Commit 852f43cd authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[wasm] Make opcode properties constexpr

This allows the compiler to eliminate more unneeded branches. Since all
functions just do a lookup in a static table (either directly, or via
compiling a switch to such a lookup), they are also good candidates for
inlining, which is made possible by this change.

One DCHECK is removed instead of pulling in the inl header, which would
require more refactoring since the check is in a non-inl header.

R=thibaudm@chromium.org
TBR=jkummerow@chromium.org

Bug: v8:10576
Change-Id: If0fd25fd62c5f30b896fc67a5458a5ae475a6351
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2259944
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68508}
parent 2d984508
......@@ -55,7 +55,7 @@
#include "src/wasm/wasm-linkage.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-opcodes-inl.h"
namespace v8 {
namespace internal {
......
......@@ -314,7 +314,7 @@ class ErrorUtils : public AllStatic {
class MessageFormatter {
public:
static const char* TemplateString(MessageTemplate index);
V8_EXPORT_PRIVATE static const char* TemplateString(MessageTemplate index);
V8_EXPORT_PRIVATE static MaybeHandle<String> Format(Isolate* isolate,
MessageTemplate index,
......
......@@ -27,7 +27,7 @@
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-linkage.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-opcodes-inl.h"
namespace v8 {
namespace internal {
......
......@@ -137,7 +137,6 @@ class Decoder {
if (length == nullptr) {
length = &unused_length;
}
DCHECK(WasmOpcodes::IsPrefixOpcode(static_cast<WasmOpcode>(*pc)));
uint32_t index;
if (*pc == WasmOpcode::kSimdPrefix) {
// SIMD opcodes can be multiple bytes (when LEB128 encoded).
......
......@@ -13,7 +13,7 @@
#include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-linkage.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-opcodes-inl.h"
namespace v8 {
namespace internal {
......
......@@ -16,7 +16,7 @@
#include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-linkage.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-opcodes-inl.h"
namespace v8 {
namespace internal {
......
......@@ -23,6 +23,7 @@
#include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-opcodes-inl.h"
#include "src/wasm/wasm-value.h"
#include "src/zone/accounting-allocator.h"
......
// Copyright 2020 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_WASM_WASM_OPCODES_INL_H_
#define V8_WASM_WASM_OPCODES_INL_H_
#include <array>
#include "src/base/template-utils.h"
#include "src/codegen/signature.h"
#include "src/execution/messages.h"
#include "src/runtime/runtime.h"
#include "src/wasm/wasm-opcodes.h"
namespace v8 {
namespace internal {
namespace wasm {
#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)
#define CASE_REF_OP(name, str) CASE_OP(Ref##name, "ref." str)
#define CASE_F64x2_OP(name, str) CASE_OP(F64x2##name, "f64x2." str)
#define CASE_F32x4_OP(name, str) CASE_OP(F32x4##name, "f32x4." str)
#define CASE_I64x2_OP(name, str) CASE_OP(I64x2##name, "i64x2." str)
#define CASE_I32x4_OP(name, str) CASE_OP(I32x4##name, "i32x4." str)
#define CASE_I16x8_OP(name, str) CASE_OP(I16x8##name, "i16x8." str)
#define CASE_I8x16_OP(name, str) CASE_OP(I8x16##name, "i8x16." str)
#define CASE_S128_OP(name, str) CASE_OP(S128##name, "s128." str)
#define CASE_S64x2_OP(name, str) CASE_OP(S64x2##name, "s64x2." str)
#define CASE_S32x4_OP(name, str) CASE_OP(S32x4##name, "s32x4." str)
#define CASE_S16x8_OP(name, str) CASE_OP(S16x8##name, "s16x8." str)
#define CASE_S8x16_OP(name, str) CASE_OP(S8x16##name, "s8x16." str)
#define CASE_V64x2_OP(name, str) CASE_OP(V64x2##name, "v64x2." str)
#define CASE_V32x4_OP(name, str) CASE_OP(V32x4##name, "v32x4." str)
#define CASE_V16x8_OP(name, str) CASE_OP(V16x8##name, "v16x8." str)
#define CASE_V8x16_OP(name, str) CASE_OP(V8x16##name, "v8x16." str)
#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) \
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)
#define CASE_SIMDI_OP(name, str) \
CASE_I32x4_OP(name, str) CASE_I16x8_OP(name, str) CASE_I8x16_OP(name, str)
#define CASE_SIMDV_OP(name, str) \
CASE_V32x4_OP(name, str) CASE_V16x8_OP(name, str) CASE_V8x16_OP(name, str)
#define CASE_SIGN_OP(TYPE, name, str) \
CASE_##TYPE##_OP(name##S, str "_s") CASE_##TYPE##_OP(name##U, str "_u")
#define CASE_UNSIGNED_OP(TYPE, name, str) CASE_##TYPE##_OP(name##U, str "_u")
#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) \
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")
#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")
#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")
#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")
// static
constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
switch (opcode) {
// clang-format off
// 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")
CASE_REF_OP(Null, "null")
CASE_REF_OP(IsNull, "is_null")
CASE_REF_OP(Func, "func")
CASE_REF_OP(AsNonNull, "as_non_null")
CASE_I32_OP(ConvertI64, "wrap_i64")
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")
CASE_F32_OP(ConvertF64, "demote_f64")
CASE_CONVERT_OP(Convert, F64, I32, "i32", "convert")
CASE_CONVERT_OP(Convert, F64, I64, "i64", "convert")
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")
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")
CASE_OP(ReturnCall, "return_call")
CASE_OP(ReturnCallIndirect, "return_call_indirect")
CASE_OP(BrOnNull, "br_on_null")
CASE_OP(Drop, "drop")
CASE_OP(Select, "select")
CASE_OP(SelectWithType, "select")
CASE_OP(LocalGet, "local.get")
CASE_OP(LocalSet, "local.set")
CASE_OP(LocalTee, "local.tee")
CASE_OP(GlobalGet, "global.get")
CASE_OP(GlobalSet, "global.set")
CASE_OP(TableGet, "table.get")
CASE_OP(TableSet, "table.set")
CASE_ALL_OP(Const, "const")
CASE_OP(MemorySize, "memory.size")
CASE_OP(MemoryGrow, "memory.grow")
CASE_ALL_OP(LoadMem, "load")
CASE_SIGN_OP(INT, LoadMem8, "load8")
CASE_SIGN_OP(INT, LoadMem16, "load16")
CASE_SIGN_OP(I64, LoadMem32, "load32")
CASE_S128_OP(LoadMem, "load128")
CASE_ALL_OP(StoreMem, "store")
CASE_INT_OP(StoreMem8, "store8")
CASE_INT_OP(StoreMem16, "store16")
CASE_I64_OP(StoreMem32, "store32")
CASE_S128_OP(StoreMem, "store128")
// Exception handling opcodes.
CASE_OP(Try, "try")
CASE_OP(Catch, "catch")
CASE_OP(Throw, "throw")
CASE_OP(Rethrow, "rethrow")
CASE_OP(BrOnExn, "br_on_exn")
// 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")
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")
// 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")
CASE_OP(DataDrop, "data.drop")
CASE_OP(MemoryCopy, "memory.copy")
CASE_OP(MemoryFill, "memory.fill")
CASE_OP(TableInit, "table.init")
CASE_OP(ElemDrop, "elem.drop")
CASE_OP(TableCopy, "table.copy")
CASE_OP(TableGrow, "table.grow")
CASE_OP(TableSize, "table.size")
CASE_OP(TableFill, "table.fill")
// SIMD opcodes.
CASE_SIMD_OP(Splat, "splat")
CASE_SIMD_OP(Neg, "neg")
CASE_SIMDF_OP(Sqrt, "sqrt")
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")
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")
CASE_F32x4_OP(AddHoriz, "add_horizontal")
CASE_F32x4_OP(RecipApprox, "recip_approx")
CASE_F32x4_OP(RecipSqrtApprox, "recip_sqrt_approx")
CASE_SIMDF_OP(Min, "min")
CASE_SIMDF_OP(Max, "max")
CASE_CONVERT_OP(Convert, F32x4, I32x4, "i32", "convert")
CASE_CONVERT_OP(Convert, I32x4, F32x4, "f32", "convert")
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")
CASE_SIMDF_OP(ExtractLane, "extract_lane")
CASE_SIMDF_OP(ReplaceLane, "replace_lane")
CASE_I64x2_OP(ExtractLane, "extract_lane")
CASE_I64x2_OP(ReplaceLane, "replace_lane")
CASE_I32x4_OP(ExtractLane, "extract_lane")
CASE_SIGN_OP(I16x8, ExtractLane, "extract_lane")
CASE_SIGN_OP(I8x16, ExtractLane, "extract_lane")
CASE_SIMDI_OP(ReplaceLane, "replace_lane")
CASE_SIGN_OP(SIMDI, Min, "min")
CASE_SIGN_OP(I64x2, Min, "min")
CASE_SIGN_OP(SIMDI, Max, "max")
CASE_SIGN_OP(I64x2, Max, "max")
CASE_SIGN_OP(SIMDI, Lt, "lt")
CASE_SIGN_OP(I64x2, Lt, "lt")
CASE_SIGN_OP(SIMDI, Le, "le")
CASE_SIGN_OP(I64x2, Le, "le")
CASE_SIGN_OP(SIMDI, Gt, "gt")
CASE_SIGN_OP(I64x2, Gt, "gt")
CASE_SIGN_OP(SIMDI, Ge, "ge")
CASE_SIGN_OP(I64x2, Ge, "ge")
CASE_SIGN_OP(SIMDI, Shr, "shr")
CASE_SIGN_OP(I64x2, Shr, "shr")
CASE_SIMDI_OP(Shl, "shl")
CASE_I64x2_OP(Shl, "shl")
CASE_I32x4_OP(AddHoriz, "add_horizontal")
CASE_I16x8_OP(AddHoriz, "add_horizontal")
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")
CASE_S128_OP(And, "and")
CASE_S128_OP(Or, "or")
CASE_S128_OP(Xor, "xor")
CASE_S128_OP(Not, "not")
CASE_S128_OP(Select, "select")
CASE_S128_OP(AndNot, "andnot")
CASE_S8x16_OP(Swizzle, "swizzle")
CASE_S8x16_OP(Shuffle, "shuffle")
CASE_SIMDV_OP(AnyTrue, "any_true")
CASE_SIMDV_OP(AllTrue, "all_true")
CASE_V64x2_OP(AnyTrue, "any_true")
CASE_V64x2_OP(AllTrue, "all_true")
CASE_SIMDF_OP(Qfma, "qfma")
CASE_SIMDF_OP(Qfms, "qfms")
CASE_S8x16_OP(LoadSplat, "load_splat")
CASE_S16x8_OP(LoadSplat, "load_splat")
CASE_S32x4_OP(LoadSplat, "load_splat")
CASE_S64x2_OP(LoadSplat, "load_splat")
CASE_I16x8_OP(Load8x8S, "load8x8_s")
CASE_I16x8_OP(Load8x8U, "load8x8_u")
CASE_I32x4_OP(Load16x4S, "load16x4_s")
CASE_I32x4_OP(Load16x4U, "load16x4_u")
CASE_I64x2_OP(Load32x2S, "load32x2_s")
CASE_I64x2_OP(Load32x2U, "load32x2_u")
CASE_I8x16_OP(RoundingAverageU, "avgr_u")
CASE_I16x8_OP(RoundingAverageU, "avgr_u")
CASE_I8x16_OP(Abs, "abs")
CASE_I16x8_OP(Abs, "abs")
CASE_I32x4_OP(Abs, "abs")
CASE_I8x16_OP(BitMask, "bitmask")
CASE_I16x8_OP(BitMask, "bitmask")
CASE_I32x4_OP(BitMask, "bitmask")
CASE_F32x4_OP(Pmin, "pmin")
CASE_F32x4_OP(Pmax, "pmax")
CASE_F64x2_OP(Pmin, "pmin")
CASE_F64x2_OP(Pmax, "pmax")
CASE_F32x4_OP(Ceil, "ceil")
CASE_F32x4_OP(Floor, "floor")
CASE_F32x4_OP(Trunc, "trunc")
CASE_F32x4_OP(NearestInt, "nearest")
CASE_F64x2_OP(Ceil, "ceil")
CASE_F64x2_OP(Floor, "floor")
CASE_F64x2_OP(Trunc, "trunc")
CASE_F64x2_OP(NearestInt, "nearest")
CASE_I32x4_OP(DotI16x8S, "dot_i16x8_s")
// Atomic operations.
CASE_OP(AtomicNotify, "atomic.notify")
CASE_INT_OP(AtomicWait, "atomic.wait")
CASE_OP(AtomicFence, "atomic.fence")
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")
// GC operations.
CASE_OP(StructNew, "struct.new")
CASE_OP(StructNewSub, "struct.new_sub")
CASE_OP(StructNewDefault, "struct.new_default")
CASE_OP(StructGet, "struct.get")
CASE_OP(StructGetS, "struct.get_s")
CASE_OP(StructGetU, "struct.get_u")
CASE_OP(StructSet, "struct.set")
CASE_OP(ArrayNew, "array.new")
CASE_OP(ArrayNewSub, "array.new_sub")
CASE_OP(ArrayNewDefault, "array.new_default")
CASE_OP(ArrayGet, "array.get")
CASE_OP(ArrayGetS, "array.get_s")
CASE_OP(ArrayGetU, "array.get_u")
CASE_OP(ArrayLen, "array.len")
CASE_OP(ArraySet, "array.set")
CASE_OP(I31New, "i31.new")
CASE_OP(I31GetS, "i31.get_s")
CASE_OP(I31GetU, "i31.get_u")
CASE_OP(RttCanon, "rtt.canon")
CASE_OP(RttSub, "rtt.sub")
CASE_OP(RefTest, "ref.test")
CASE_OP(RefCast, "ref.cast")
CASE_OP(BrOnCast, "br_on_cast")
CASE_OP(RefEq, "ref.eq")
CASE_OP(Let, "let")
case kNumericPrefix:
case kSimdPrefix:
case kAtomicPrefix:
case kGCPrefix:
return "unknown";
// clang-format on
}
// Even though the switch above handles all well-defined enum values,
// random modules (e.g. fuzzer generated) can call this function with
// random (invalid) opcodes. Handle those here:
return "invalid opcode";
}
#undef CASE_OP
#undef CASE_I32_OP
#undef CASE_I64_OP
#undef CASE_F32_OP
#undef CASE_F64_OP
#undef CASE_REF_OP
#undef CASE_F64x2_OP
#undef CASE_F32x4_OP
#undef CASE_I64x2_OP
#undef CASE_I32x4_OP
#undef CASE_I16x8_OP
#undef CASE_I8x16_OP
#undef CASE_S128_OP
#undef CASE_S64x2_OP
#undef CASE_S32x4_OP
#undef CASE_S16x8_OP
#undef CASE_S8x16_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
#undef CASE_UNSIGNED_ALL_OP
#undef CASE_ALL_SIGN_OP
#undef CASE_CONVERT_OP
#undef CASE_CONVERT_SAT_OP
#undef CASE_L32_OP
#undef CASE_U32_OP
// static
constexpr bool WasmOpcodes::IsPrefixOpcode(WasmOpcode opcode) {
switch (opcode) {
#define CHECK_PREFIX(name, opcode) case k##name##Prefix:
FOREACH_PREFIX(CHECK_PREFIX)
#undef CHECK_PREFIX
return true;
default:
return false;
}
}
// static
constexpr bool WasmOpcodes::IsControlOpcode(WasmOpcode opcode) {
switch (opcode) {
#define CHECK_OPCODE(name, opcode, _) case kExpr##name:
FOREACH_CONTROL_OPCODE(CHECK_OPCODE)
#undef CHECK_OPCODE
return true;
default:
return false;
}
}
// static
constexpr bool WasmOpcodes::IsUnconditionalJump(WasmOpcode opcode) {
switch (opcode) {
case kExprUnreachable:
case kExprBr:
case kExprBrTable:
case kExprReturn:
return true;
default:
return false;
}
}
// static
constexpr bool WasmOpcodes::IsBreakable(WasmOpcode opcode) {
switch (opcode) {
case kExprBlock:
case kExprTry:
case kExprCatch:
case kExprLoop:
case kExprElse:
return false;
default:
return true;
}
}
// static
constexpr bool WasmOpcodes::IsExternRefOpcode(WasmOpcode opcode) {
switch (opcode) {
case kExprRefNull:
case kExprRefIsNull:
case kExprRefFunc:
case kExprRefAsNonNull:
return true;
default:
return false;
}
}
// static
constexpr 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;
}
}
// static
constexpr 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;
}
}
namespace impl {
#define DECLARE_SIG_ENUM(name, ...) kSigEnum_##name,
enum WasmOpcodeSig : byte {
kSigEnum_None,
FOREACH_SIGNATURE(DECLARE_SIG_ENUM)
};
#undef DECLARE_SIG_ENUM
#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));
FOREACH_SIGNATURE(DECLARE_SIG)
#undef DECLARE_SIG
#define DECLARE_SIG_ENTRY(name, ...) &kSig_##name,
constexpr const FunctionSig* kCachedSigs[] = {
nullptr, FOREACH_SIGNATURE(DECLARE_SIG_ENTRY)};
#undef DECLARE_SIG_ENTRY
constexpr WasmOpcodeSig GetShortOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == opc ? kSigEnum_##sig:
return FOREACH_SIMPLE_OPCODE(CASE) FOREACH_SIMPLE_PROTOTYPE_OPCODE(CASE)
kSigEnum_None;
#undef CASE
}
constexpr WasmOpcodeSig GetAsmJsOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == opc ? kSigEnum_##sig:
return FOREACH_ASMJS_COMPAT_OPCODE(CASE) kSigEnum_None;
#undef CASE
}
constexpr WasmOpcodeSig GetSimdOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
return FOREACH_SIMD_0_OPERAND_OPCODE(CASE) FOREACH_SIMD_MEM_OPCODE(CASE)
kSigEnum_None;
#undef CASE
}
constexpr WasmOpcodeSig GetAtomicOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
return FOREACH_ATOMIC_OPCODE(CASE) FOREACH_ATOMIC_0_OPERAND_OPCODE(CASE)
kSigEnum_None;
#undef CASE
}
constexpr WasmOpcodeSig GetNumericOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
return FOREACH_NUMERIC_OPCODE(CASE) kSigEnum_None;
#undef CASE
}
constexpr std::array<WasmOpcodeSig, 256> kShortSigTable =
base::make_array<256>(GetShortOpcodeSigIndex);
constexpr std::array<WasmOpcodeSig, 256> kSimpleAsmjsExprSigTable =
base::make_array<256>(GetAsmJsOpcodeSigIndex);
constexpr std::array<WasmOpcodeSig, 256> kSimdExprSigTable =
base::make_array<256>(GetSimdOpcodeSigIndex);
constexpr std::array<WasmOpcodeSig, 256> kAtomicExprSigTable =
base::make_array<256>(GetAtomicOpcodeSigIndex);
constexpr std::array<WasmOpcodeSig, 256> kNumericExprSigTable =
base::make_array<256>(GetNumericOpcodeSigIndex);
} // namespace impl
constexpr const FunctionSig* WasmOpcodes::Signature(WasmOpcode opcode) {
switch (opcode >> 8) {
case 0:
return impl::kCachedSigs[impl::kShortSigTable[opcode]];
case kSimdPrefix:
return impl::kCachedSigs[impl::kSimdExprSigTable[opcode & 0xFF]];
case kAtomicPrefix:
return impl::kCachedSigs[impl::kAtomicExprSigTable[opcode & 0xFF]];
case kNumericPrefix:
return impl::kCachedSigs[impl::kNumericExprSigTable[opcode & 0xFF]];
default:
#if V8_HAS_CXX14_CONSTEXPR
UNREACHABLE(); // invalid prefix.
#else
return nullptr;
#endif
}
}
constexpr const FunctionSig* WasmOpcodes::AsmjsSignature(WasmOpcode opcode) {
CONSTEXPR_DCHECK(opcode < impl::kSimpleAsmjsExprSigTable.size());
return impl::kCachedSigs[impl::kSimpleAsmjsExprSigTable[opcode]];
}
constexpr MessageTemplate WasmOpcodes::TrapReasonToMessageId(
TrapReason reason) {
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) {
return MessageFormatter::TemplateString(TrapReasonToMessageId(reason));
}
} // namespace wasm
} // namespace internal
} // namespace v8
#endif // V8_WASM_WASM_OPCODES_INL_H_
......@@ -6,506 +6,14 @@
#include <array>
#include "src/base/template-utils.h"
#include "src/codegen/signature.h"
#include "src/execution/messages.h"
#include "src/runtime/runtime.h"
#include "src/wasm/wasm-features.h"
#include "src/wasm/wasm-opcodes-inl.h"
namespace v8 {
namespace internal {
namespace wasm {
#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)
#define CASE_REF_OP(name, str) CASE_OP(Ref##name, "ref." str)
#define CASE_F64x2_OP(name, str) CASE_OP(F64x2##name, "f64x2." str)
#define CASE_F32x4_OP(name, str) CASE_OP(F32x4##name, "f32x4." str)
#define CASE_I64x2_OP(name, str) CASE_OP(I64x2##name, "i64x2." str)
#define CASE_I32x4_OP(name, str) CASE_OP(I32x4##name, "i32x4." str)
#define CASE_I16x8_OP(name, str) CASE_OP(I16x8##name, "i16x8." str)
#define CASE_I8x16_OP(name, str) CASE_OP(I8x16##name, "i8x16." str)
#define CASE_S128_OP(name, str) CASE_OP(S128##name, "s128." str)
#define CASE_S64x2_OP(name, str) CASE_OP(S64x2##name, "s64x2." str)
#define CASE_S32x4_OP(name, str) CASE_OP(S32x4##name, "s32x4." str)
#define CASE_S16x8_OP(name, str) CASE_OP(S16x8##name, "s16x8." str)
#define CASE_S8x16_OP(name, str) CASE_OP(S8x16##name, "s8x16." str)
#define CASE_V64x2_OP(name, str) CASE_OP(V64x2##name, "v64x2." str)
#define CASE_V32x4_OP(name, str) CASE_OP(V32x4##name, "v32x4." str)
#define CASE_V16x8_OP(name, str) CASE_OP(V16x8##name, "v16x8." str)
#define CASE_V8x16_OP(name, str) CASE_OP(V8x16##name, "v8x16." str)
#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) \
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)
#define CASE_SIMDI_OP(name, str) \
CASE_I32x4_OP(name, str) CASE_I16x8_OP(name, str) CASE_I8x16_OP(name, str)
#define CASE_SIMDV_OP(name, str) \
CASE_V32x4_OP(name, str) CASE_V16x8_OP(name, str) CASE_V8x16_OP(name, str)
#define CASE_SIGN_OP(TYPE, name, str) \
CASE_##TYPE##_OP(name##S, str "_s") CASE_##TYPE##_OP(name##U, str "_u")
#define CASE_UNSIGNED_OP(TYPE, name, str) CASE_##TYPE##_OP(name##U, str "_u")
#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) \
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")
#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")
#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")
#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")
const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
switch (opcode) {
// clang-format off
// 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")
CASE_REF_OP(Null, "null")
CASE_REF_OP(IsNull, "is_null")
CASE_REF_OP(Func, "func")
CASE_REF_OP(AsNonNull, "as_non_null")
CASE_I32_OP(ConvertI64, "wrap_i64")
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")
CASE_F32_OP(ConvertF64, "demote_f64")
CASE_CONVERT_OP(Convert, F64, I32, "i32", "convert")
CASE_CONVERT_OP(Convert, F64, I64, "i64", "convert")
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")
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")
CASE_OP(ReturnCall, "return_call")
CASE_OP(ReturnCallIndirect, "return_call_indirect")
CASE_OP(BrOnNull, "br_on_null")
CASE_OP(Drop, "drop")
CASE_OP(Select, "select")
CASE_OP(SelectWithType, "select")
CASE_OP(LocalGet, "local.get")
CASE_OP(LocalSet, "local.set")
CASE_OP(LocalTee, "local.tee")
CASE_OP(GlobalGet, "global.get")
CASE_OP(GlobalSet, "global.set")
CASE_OP(TableGet, "table.get")
CASE_OP(TableSet, "table.set")
CASE_ALL_OP(Const, "const")
CASE_OP(MemorySize, "memory.size")
CASE_OP(MemoryGrow, "memory.grow")
CASE_ALL_OP(LoadMem, "load")
CASE_SIGN_OP(INT, LoadMem8, "load8")
CASE_SIGN_OP(INT, LoadMem16, "load16")
CASE_SIGN_OP(I64, LoadMem32, "load32")
CASE_S128_OP(LoadMem, "load128")
CASE_ALL_OP(StoreMem, "store")
CASE_INT_OP(StoreMem8, "store8")
CASE_INT_OP(StoreMem16, "store16")
CASE_I64_OP(StoreMem32, "store32")
CASE_S128_OP(StoreMem, "store128")
// Exception handling opcodes.
CASE_OP(Try, "try")
CASE_OP(Catch, "catch")
CASE_OP(Throw, "throw")
CASE_OP(Rethrow, "rethrow")
CASE_OP(BrOnExn, "br_on_exn")
// 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")
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")
// 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")
CASE_OP(DataDrop, "data.drop")
CASE_OP(MemoryCopy, "memory.copy")
CASE_OP(MemoryFill, "memory.fill")
CASE_OP(TableInit, "table.init")
CASE_OP(ElemDrop, "elem.drop")
CASE_OP(TableCopy, "table.copy")
CASE_OP(TableGrow, "table.grow")
CASE_OP(TableSize, "table.size")
CASE_OP(TableFill, "table.fill")
// SIMD opcodes.
CASE_SIMD_OP(Splat, "splat")
CASE_SIMD_OP(Neg, "neg")
CASE_SIMDF_OP(Sqrt, "sqrt")
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")
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")
CASE_F32x4_OP(AddHoriz, "add_horizontal")
CASE_F32x4_OP(RecipApprox, "recip_approx")
CASE_F32x4_OP(RecipSqrtApprox, "recip_sqrt_approx")
CASE_SIMDF_OP(Min, "min")
CASE_SIMDF_OP(Max, "max")
CASE_CONVERT_OP(Convert, F32x4, I32x4, "i32", "convert")
CASE_CONVERT_OP(Convert, I32x4, F32x4, "f32", "convert")
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")
CASE_SIMDF_OP(ExtractLane, "extract_lane")
CASE_SIMDF_OP(ReplaceLane, "replace_lane")
CASE_I64x2_OP(ExtractLane, "extract_lane")
CASE_I64x2_OP(ReplaceLane, "replace_lane")
CASE_I32x4_OP(ExtractLane, "extract_lane")
CASE_SIGN_OP(I16x8, ExtractLane, "extract_lane")
CASE_SIGN_OP(I8x16, ExtractLane, "extract_lane")
CASE_SIMDI_OP(ReplaceLane, "replace_lane")
CASE_SIGN_OP(SIMDI, Min, "min")
CASE_SIGN_OP(I64x2, Min, "min")
CASE_SIGN_OP(SIMDI, Max, "max")
CASE_SIGN_OP(I64x2, Max, "max")
CASE_SIGN_OP(SIMDI, Lt, "lt")
CASE_SIGN_OP(I64x2, Lt, "lt")
CASE_SIGN_OP(SIMDI, Le, "le")
CASE_SIGN_OP(I64x2, Le, "le")
CASE_SIGN_OP(SIMDI, Gt, "gt")
CASE_SIGN_OP(I64x2, Gt, "gt")
CASE_SIGN_OP(SIMDI, Ge, "ge")
CASE_SIGN_OP(I64x2, Ge, "ge")
CASE_SIGN_OP(SIMDI, Shr, "shr")
CASE_SIGN_OP(I64x2, Shr, "shr")
CASE_SIMDI_OP(Shl, "shl")
CASE_I64x2_OP(Shl, "shl")
CASE_I32x4_OP(AddHoriz, "add_horizontal")
CASE_I16x8_OP(AddHoriz, "add_horizontal")
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")
CASE_S128_OP(And, "and")
CASE_S128_OP(Or, "or")
CASE_S128_OP(Xor, "xor")
CASE_S128_OP(Not, "not")
CASE_S128_OP(Select, "select")
CASE_S128_OP(AndNot, "andnot")
CASE_S8x16_OP(Swizzle, "swizzle")
CASE_S8x16_OP(Shuffle, "shuffle")
CASE_SIMDV_OP(AnyTrue, "any_true")
CASE_SIMDV_OP(AllTrue, "all_true")
CASE_V64x2_OP(AnyTrue, "any_true")
CASE_V64x2_OP(AllTrue, "all_true")
CASE_SIMDF_OP(Qfma, "qfma")
CASE_SIMDF_OP(Qfms, "qfms")
CASE_S8x16_OP(LoadSplat, "load_splat")
CASE_S16x8_OP(LoadSplat, "load_splat")
CASE_S32x4_OP(LoadSplat, "load_splat")
CASE_S64x2_OP(LoadSplat, "load_splat")
CASE_I16x8_OP(Load8x8S, "load8x8_s")
CASE_I16x8_OP(Load8x8U, "load8x8_u")
CASE_I32x4_OP(Load16x4S, "load16x4_s")
CASE_I32x4_OP(Load16x4U, "load16x4_u")
CASE_I64x2_OP(Load32x2S, "load32x2_s")
CASE_I64x2_OP(Load32x2U, "load32x2_u")
CASE_I8x16_OP(RoundingAverageU, "avgr_u")
CASE_I16x8_OP(RoundingAverageU, "avgr_u")
CASE_I8x16_OP(Abs, "abs")
CASE_I16x8_OP(Abs, "abs")
CASE_I32x4_OP(Abs, "abs")
CASE_I8x16_OP(BitMask, "bitmask")
CASE_I16x8_OP(BitMask, "bitmask")
CASE_I32x4_OP(BitMask, "bitmask")
CASE_F32x4_OP(Pmin, "pmin")
CASE_F32x4_OP(Pmax, "pmax")
CASE_F64x2_OP(Pmin, "pmin")
CASE_F64x2_OP(Pmax, "pmax")
CASE_F32x4_OP(Ceil, "ceil")
CASE_F32x4_OP(Floor, "floor")
CASE_F32x4_OP(Trunc, "trunc")
CASE_F32x4_OP(NearestInt, "nearest")
CASE_F64x2_OP(Ceil, "ceil")
CASE_F64x2_OP(Floor, "floor")
CASE_F64x2_OP(Trunc, "trunc")
CASE_F64x2_OP(NearestInt, "nearest")
CASE_I32x4_OP(DotI16x8S, "dot_i16x8_s")
// Atomic operations.
CASE_OP(AtomicNotify, "atomic.notify")
CASE_INT_OP(AtomicWait, "atomic.wait")
CASE_OP(AtomicFence, "atomic.fence")
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")
// GC operations.
CASE_OP(StructNew, "struct.new")
CASE_OP(StructNewSub, "struct.new_sub")
CASE_OP(StructNewDefault, "struct.new_default")
CASE_OP(StructGet, "struct.get")
CASE_OP(StructGetS, "struct.get_s")
CASE_OP(StructGetU, "struct.get_u")
CASE_OP(StructSet, "struct.set")
CASE_OP(ArrayNew, "array.new")
CASE_OP(ArrayNewSub, "array.new_sub")
CASE_OP(ArrayNewDefault, "array.new_default")
CASE_OP(ArrayGet, "array.get")
CASE_OP(ArrayGetS, "array.get_s")
CASE_OP(ArrayGetU, "array.get_u")
CASE_OP(ArrayLen, "array.len")
CASE_OP(ArraySet, "array.set")
CASE_OP(I31New, "i31.new")
CASE_OP(I31GetS, "i31.get_s")
CASE_OP(I31GetU, "i31.get_u")
CASE_OP(RttCanon, "rtt.canon")
CASE_OP(RttSub, "rtt.sub")
CASE_OP(RefTest, "ref.test")
CASE_OP(RefCast, "ref.cast")
CASE_OP(BrOnCast, "br_on_cast")
CASE_OP(RefEq, "ref.eq")
CASE_OP(Let, "let")
case kNumericPrefix:
case kSimdPrefix:
case kAtomicPrefix:
case kGCPrefix:
return "unknown";
// clang-format on
}
// Even though the switch above handles all well-defined enum values,
// random modules (e.g. fuzzer generated) can call this function with
// random (invalid) opcodes. Handle those here:
return "invalid opcode";
}
#undef CASE_OP
#undef CASE_I32_OP
#undef CASE_I64_OP
#undef CASE_F32_OP
#undef CASE_F64_OP
#undef CASE_REF_OP
#undef CASE_F64x2_OP
#undef CASE_F32x4_OP
#undef CASE_I64x2_OP
#undef CASE_I32x4_OP
#undef CASE_I16x8_OP
#undef CASE_I8x16_OP
#undef CASE_S128_OP
#undef CASE_S64x2_OP
#undef CASE_S32x4_OP
#undef CASE_S16x8_OP
#undef CASE_S8x16_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
#undef CASE_UNSIGNED_ALL_OP
#undef CASE_ALL_SIGN_OP
#undef CASE_CONVERT_OP
#undef CASE_CONVERT_SAT_OP
#undef CASE_L32_OP
#undef CASE_U32_OP
bool WasmOpcodes::IsPrefixOpcode(WasmOpcode opcode) {
switch (opcode) {
#define CHECK_PREFIX(name, opcode) case k##name##Prefix:
FOREACH_PREFIX(CHECK_PREFIX)
#undef CHECK_PREFIX
return true;
default:
return false;
}
}
bool WasmOpcodes::IsControlOpcode(WasmOpcode opcode) {
switch (opcode) {
#define CHECK_OPCODE(name, opcode, _) case kExpr##name:
FOREACH_CONTROL_OPCODE(CHECK_OPCODE)
#undef CHECK_OPCODE
return true;
default:
return false;
}
}
bool WasmOpcodes::IsUnconditionalJump(WasmOpcode opcode) {
switch (opcode) {
case kExprUnreachable:
case kExprBr:
case kExprBrTable:
case kExprReturn:
return true;
default:
return false;
}
}
bool WasmOpcodes::IsBreakable(WasmOpcode opcode) {
switch (opcode) {
case kExprBlock:
case kExprTry:
case kExprCatch:
case kExprLoop:
case kExprElse:
return false;
default:
return true;
}
}
bool WasmOpcodes::IsExternRefOpcode(WasmOpcode opcode) {
switch (opcode) {
case kExprRefNull:
case kExprRefIsNull:
case kExprRefFunc:
case kExprRefAsNonNull:
return true;
default:
return false;
}
}
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;
}
}
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;
}
}
std::ostream& operator<<(std::ostream& os, const FunctionSig& sig) {
if (sig.return_count() == 0) os << "v";
for (auto ret : sig.returns()) {
......@@ -534,95 +42,6 @@ bool IsJSCompatibleSignature(const FunctionSig* sig,
return true;
}
namespace {
#define DECLARE_SIG_ENUM(name, ...) kSigEnum_##name,
enum WasmOpcodeSig : byte {
kSigEnum_None,
FOREACH_SIGNATURE(DECLARE_SIG_ENUM)
};
#undef DECLARE_SIG_ENUM
#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));
FOREACH_SIGNATURE(DECLARE_SIG)
#undef DECLARE_SIG
#define DECLARE_SIG_ENTRY(name, ...) &kSig_##name,
constexpr const FunctionSig* kCachedSigs[] = {
nullptr, FOREACH_SIGNATURE(DECLARE_SIG_ENTRY)};
#undef DECLARE_SIG_ENTRY
constexpr WasmOpcodeSig GetShortOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == opc ? kSigEnum_##sig:
return FOREACH_SIMPLE_OPCODE(CASE) FOREACH_SIMPLE_PROTOTYPE_OPCODE(CASE)
kSigEnum_None;
#undef CASE
}
constexpr WasmOpcodeSig GetAsmJsOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == opc ? kSigEnum_##sig:
return FOREACH_ASMJS_COMPAT_OPCODE(CASE) kSigEnum_None;
#undef CASE
}
constexpr WasmOpcodeSig GetSimdOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
return FOREACH_SIMD_0_OPERAND_OPCODE(CASE) FOREACH_SIMD_MEM_OPCODE(CASE)
kSigEnum_None;
#undef CASE
}
constexpr WasmOpcodeSig GetAtomicOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
return FOREACH_ATOMIC_OPCODE(CASE) FOREACH_ATOMIC_0_OPERAND_OPCODE(CASE)
kSigEnum_None;
#undef CASE
}
constexpr WasmOpcodeSig GetNumericOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
return FOREACH_NUMERIC_OPCODE(CASE) kSigEnum_None;
#undef CASE
}
constexpr std::array<WasmOpcodeSig, 256> kShortSigTable =
base::make_array<256>(GetShortOpcodeSigIndex);
constexpr std::array<WasmOpcodeSig, 256> kSimpleAsmjsExprSigTable =
base::make_array<256>(GetAsmJsOpcodeSigIndex);
constexpr std::array<WasmOpcodeSig, 256> kSimdExprSigTable =
base::make_array<256>(GetSimdOpcodeSigIndex);
constexpr std::array<WasmOpcodeSig, 256> kAtomicExprSigTable =
base::make_array<256>(GetAtomicOpcodeSigIndex);
constexpr std::array<WasmOpcodeSig, 256> kNumericExprSigTable =
base::make_array<256>(GetNumericOpcodeSigIndex);
} // namespace
const FunctionSig* WasmOpcodes::Signature(WasmOpcode opcode) {
switch (opcode >> 8) {
case 0:
return kCachedSigs[kShortSigTable[opcode]];
case kSimdPrefix:
return kCachedSigs[kSimdExprSigTable[opcode & 0xFF]];
case kAtomicPrefix:
return kCachedSigs[kAtomicExprSigTable[opcode & 0xFF]];
case kNumericPrefix:
return kCachedSigs[kNumericExprSigTable[opcode & 0xFF]];
default:
UNREACHABLE(); // invalid prefix.
return nullptr;
}
}
const FunctionSig* WasmOpcodes::AsmjsSignature(WasmOpcode opcode) {
DCHECK_GT(kSimpleAsmjsExprSigTable.size(), opcode);
return kCachedSigs[kSimpleAsmjsExprSigTable[opcode]];
}
// Define constexpr arrays.
constexpr uint8_t LoadType::kLoadSizeLog2[];
constexpr ValueType LoadType::kValueType[];
......@@ -631,21 +50,6 @@ constexpr uint8_t StoreType::kStoreSizeLog2[];
constexpr ValueType StoreType::kValueType[];
constexpr MachineRepresentation StoreType::kMemRep[];
MessageTemplate WasmOpcodes::TrapReasonToMessageId(TrapReason reason) {
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) {
return MessageFormatter::TemplateString(TrapReasonToMessageId(reason));
}
} // namespace wasm
} // namespace internal
} // namespace v8
......@@ -728,21 +728,21 @@ enum TrapReason {
// A collection of opcode-related static methods.
class V8_EXPORT_PRIVATE WasmOpcodes {
public:
static const char* OpcodeName(WasmOpcode);
static const FunctionSig* Signature(WasmOpcode);
static const FunctionSig* AsmjsSignature(WasmOpcode);
static bool IsPrefixOpcode(WasmOpcode);
static bool IsControlOpcode(WasmOpcode);
static bool IsExternRefOpcode(WasmOpcode);
static bool IsThrowingOpcode(WasmOpcode);
static bool IsSimdPostMvpOpcode(WasmOpcode);
static constexpr const char* OpcodeName(WasmOpcode);
static constexpr const FunctionSig* Signature(WasmOpcode);
static constexpr const FunctionSig* AsmjsSignature(WasmOpcode);
static constexpr bool IsPrefixOpcode(WasmOpcode);
static constexpr bool IsControlOpcode(WasmOpcode);
static constexpr bool IsExternRefOpcode(WasmOpcode);
static constexpr bool IsThrowingOpcode(WasmOpcode);
static constexpr bool IsSimdPostMvpOpcode(WasmOpcode);
// Check whether the given opcode always jumps, i.e. all instructions after
// this one in the current block are dead. Returns false for |end|.
static bool IsUnconditionalJump(WasmOpcode);
static bool IsBreakable(WasmOpcode);
static constexpr bool IsUnconditionalJump(WasmOpcode);
static constexpr bool IsBreakable(WasmOpcode);
static MessageTemplate TrapReasonToMessageId(TrapReason);
static const char* TrapReasonMessage(TrapReason);
static constexpr MessageTemplate TrapReasonToMessageId(TrapReason);
static inline const char* TrapReasonMessage(TrapReason);
};
// Representation of an initializer expression.
......
......@@ -11,6 +11,7 @@
#include "src/base/platform/elapsed-timer.h"
#include "src/codegen/assembler-inl.h"
#include "src/utils/utils.h"
#include "src/wasm/wasm-opcodes-inl.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/value-helper.h"
#include "test/cctest/wasm/wasm-run-utils.h"
......
......@@ -26,7 +26,7 @@
#include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-opcodes-inl.h"
#include "src/zone/accounting-allocator.h"
#include "src/zone/zone-containers.h"
......
......@@ -15,7 +15,7 @@
#include "src/utils/ostreams.h"
#include "src/wasm/wasm-module-builder.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-opcodes-inl.h"
#include "test/common/wasm/flag-utils.h"
#include "test/common/wasm/test-signatures.h"
#include "test/common/wasm/wasm-module-runner.h"
......
......@@ -2,24 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/wasm/leb-helper.h"
#include "test/unittests/test-utils.h"
#include "src/wasm/function-body-decoder.h"
#include "src/init/v8.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
#include "src/utils/ostreams.h"
#include "src/wasm/function-body-decoder-impl.h"
#include "src/wasm/function-body-decoder.h"
#include "src/wasm/leb-helper.h"
#include "src/wasm/local-decl-encoder.h"
#include "src/wasm/signature-map.h"
#include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-opcodes-inl.h"
#include "test/common/wasm/flag-utils.h"
#include "test/common/wasm/test-signatures.h"
#include "test/common/wasm/wasm-macro-gen.h"
#include "test/unittests/test-utils.h"
#include "testing/gmock-support.h"
namespace v8 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment