%PDF- %PDF-
Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/wasm/ |
Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/wasm/wasm-opcodes-inl.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. #if !V8_ENABLE_WEBASSEMBLY #error This header should only be included if WebAssembly is enabled. #endif // !V8_ENABLE_WEBASSEMBLY #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/wasm/wasm-opcodes.h" namespace v8 { namespace internal { namespace wasm { // static constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) { switch (opcode) { #define CASE(opcode, binary, sig, name, ...) \ case kExpr##opcode: \ return name; FOREACH_OPCODE(CASE) #undef CASE case kNumericPrefix: case kSimdPrefix: case kAtomicPrefix: case kGCPrefix: return "unknown"; } // 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"; } // 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, ...) 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: case kExprReturnCall: case kExprReturnCallIndirect: case kExprThrow: case kExprRethrow: 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::IsRelaxedSimdOpcode(WasmOpcode opcode) { // Relaxed SIMD opcodes have the SIMD prefix (0xfd) shifted by 12 bits, and // nibble 3 must be 0x1. I.e. their encoded opcode is in [0xfd100, 0xfd1ff]. static_assert(kSimdPrefix == 0xfd); #define CHECK_OPCODE(name, opcode, ...) \ static_assert((opcode & 0xfff00) == 0xfd100); FOREACH_RELAXED_SIMD_OPCODE(CHECK_OPCODE) #undef CHECK_OPCODE return (opcode & 0xfff00) == 0xfd100; } constexpr uint8_t WasmOpcodes::ExtractPrefix(WasmOpcode opcode) { // See comment on {WasmOpcode} for the encoding. return (opcode > 0xffff) ? opcode >> 12 : opcode >> 8; } namespace impl { #define DECLARE_SIG_ENUM(name, ...) kSigEnum_##name, enum WasmOpcodeSig : uint8_t { 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] == kWasmVoid ? 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(uint8_t 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(uint8_t opcode) { #define CASE(name, opc, sig, ...) opcode == opc ? kSigEnum_##sig: return FOREACH_ASMJS_COMPAT_OPCODE(CASE) kSigEnum_None; #undef CASE } constexpr WasmOpcodeSig GetSimdOpcodeSigIndex(uint8_t opcode) { #define CASE(name, opc, sig, ...) opcode == (opc & 0xFF) ? kSigEnum_##sig: return FOREACH_SIMD_MVP_0_OPERAND_OPCODE(CASE) FOREACH_SIMD_MEM_OPCODE(CASE) FOREACH_SIMD_MEM_1_OPERAND_OPCODE(CASE) kSigEnum_None; #undef CASE } constexpr WasmOpcodeSig GetRelaxedSimdOpcodeSigIndex(uint8_t opcode) { #define CASE(name, opc, sig, ...) opcode == (opc & 0xFF) ? kSigEnum_##sig: return FOREACH_RELAXED_SIMD_OPCODE(CASE) kSigEnum_None; #undef CASE } constexpr WasmOpcodeSig GetAtomicOpcodeMem32SigIndex(uint8_t 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 GetAtomicOpcodeMem64SigIndex(uint8_t opcode) { #define CASE(name, opc, sig32, text, sig64) \ opcode == (opc & 0xFF) ? kSigEnum_##sig64: return FOREACH_ATOMIC_OPCODE(CASE) FOREACH_ATOMIC_0_OPERAND_OPCODE(CASE) kSigEnum_None; #undef CASE } constexpr WasmOpcodeSig GetNumericOpcodeSigIndex(uint8_t opcode) { #define CASE(name, opc, sig, ...) opcode == (opc & 0xFF) ? kSigEnum_##sig: return FOREACH_NUMERIC_OPCODE_WITH_SIG(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> kRelaxedSimdExprSigTable = base::make_array<256>(GetRelaxedSimdOpcodeSigIndex); constexpr std::array<WasmOpcodeSig, 256> kAtomicExprSigTableMem32 = base::make_array<256>(GetAtomicOpcodeMem32SigIndex); constexpr std::array<WasmOpcodeSig, 256> kAtomicExprSigTableMem64 = base::make_array<256>(GetAtomicOpcodeMem64SigIndex); constexpr std::array<WasmOpcodeSig, 256> kNumericExprSigTable = base::make_array<256>(GetNumericOpcodeSigIndex); } // namespace impl constexpr const FunctionSig* WasmOpcodes::Signature(WasmOpcode opcode) { switch (ExtractPrefix(opcode)) { case 0: DCHECK_GT(impl::kShortSigTable.size(), opcode); return impl::kCachedSigs[impl::kShortSigTable[opcode]]; case kSimdPrefix: { // Handle SIMD MVP opcodes (in [0xfd00, 0xfdff]). if (opcode <= 0xfdff) { DCHECK_LE(0xfd00, opcode); return impl::kCachedSigs[impl::kSimdExprSigTable[opcode & 0xff]]; } // Handle relaxed SIMD opcodes (in [0xfd100, 0xfd1ff]). if (IsRelaxedSimdOpcode(opcode)) { return impl::kCachedSigs[impl::kRelaxedSimdExprSigTable[opcode & 0xff]]; } return nullptr; } case kNumericPrefix: return impl::kCachedSigs[impl::kNumericExprSigTable[opcode & 0xff]]; default: UNREACHABLE(); // invalid prefix. } } constexpr const FunctionSig* WasmOpcodes::SignatureForAtomicOp( WasmOpcode opcode, bool is_memory64) { if (is_memory64) { return impl::kCachedSigs[impl::kAtomicExprSigTableMem64[opcode & 0xff]]; } else { return impl::kCachedSigs[impl::kAtomicExprSigTableMem32[opcode & 0xff]]; } } constexpr const FunctionSig* WasmOpcodes::AsmjsSignature(WasmOpcode opcode) { DCHECK_GT(impl::kSimpleAsmjsExprSigTable.size(), opcode); 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 case kTrapCount: UNREACHABLE(); } } constexpr TrapReason WasmOpcodes::MessageIdToTrapReason( MessageTemplate message) { switch (message) { #define MESSAGE_TO_TRAPREASON(name) \ case MessageTemplate::kWasm##name: \ return k##name; FOREACH_WASM_TRAPREASON(MESSAGE_TO_TRAPREASON) #undef MESSAGE_TO_TRAPREASON default: UNREACHABLE(); } } const char* WasmOpcodes::TrapReasonMessage(TrapReason reason) { return MessageFormatter::TemplateString(TrapReasonToMessageId(reason)); } } // namespace wasm } // namespace internal } // namespace v8 #endif // V8_WASM_WASM_OPCODES_INL_H_