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 #include "src/messages.h"
7 #include "src/signature.h"
8
9 namespace v8 {
10 namespace internal {
11 namespace wasm {
12
13 typedef Signature<LocalType> FunctionSig;
14
OpcodeName(WasmOpcode opcode)15 const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
16 switch (opcode) {
17 #define DECLARE_NAME_CASE(name, opcode, sig) \
18 case kExpr##name: \
19 return "Expr" #name;
20 FOREACH_OPCODE(DECLARE_NAME_CASE)
21 #undef DECLARE_NAME_CASE
22 default:
23 break;
24 }
25 return "Unknown";
26 }
27
ShortOpcodeName(WasmOpcode opcode)28 const char* WasmOpcodes::ShortOpcodeName(WasmOpcode opcode) {
29 switch (opcode) {
30 #define DECLARE_NAME_CASE(name, opcode, sig) \
31 case kExpr##name: \
32 return #name;
33 FOREACH_OPCODE(DECLARE_NAME_CASE)
34 #undef DECLARE_NAME_CASE
35 default:
36 break;
37 }
38 return "Unknown";
39 }
40
IsPrefixOpcode(WasmOpcode opcode)41 bool WasmOpcodes::IsPrefixOpcode(WasmOpcode opcode) {
42 switch (opcode) {
43 #define CHECK_PREFIX(name, opcode) \
44 case k##name##Prefix: \
45 return true;
46 FOREACH_PREFIX(CHECK_PREFIX)
47 #undef CHECK_PREFIX
48 default:
49 return false;
50 }
51 }
52
operator <<(std::ostream & os,const FunctionSig & sig)53 std::ostream& operator<<(std::ostream& os, const FunctionSig& sig) {
54 if (sig.return_count() == 0) os << "v";
55 for (size_t i = 0; i < sig.return_count(); ++i) {
56 os << WasmOpcodes::ShortNameOf(sig.GetReturn(i));
57 }
58 os << "_";
59 if (sig.parameter_count() == 0) os << "v";
60 for (size_t i = 0; i < sig.parameter_count(); ++i) {
61 os << WasmOpcodes::ShortNameOf(sig.GetParam(i));
62 }
63 return os;
64 }
65
66 #define DECLARE_SIG_ENUM(name, ...) kSigEnum_##name,
67
68 enum WasmOpcodeSig { FOREACH_SIGNATURE(DECLARE_SIG_ENUM) };
69
70 // TODO(titzer): not static-initializer safe. Wrap in LazyInstance.
71 #define DECLARE_SIG(name, ...) \
72 static LocalType kTypes_##name[] = {__VA_ARGS__}; \
73 static const FunctionSig kSig_##name( \
74 1, static_cast<int>(arraysize(kTypes_##name)) - 1, kTypes_##name);
75
76 FOREACH_SIGNATURE(DECLARE_SIG)
77
78 #define DECLARE_SIG_ENTRY(name, ...) &kSig_##name,
79
80 static const FunctionSig* kSimpleExprSigs[] = {
81 nullptr, FOREACH_SIGNATURE(DECLARE_SIG_ENTRY)};
82
83 #define DECLARE_SIMD_SIG_ENTRY(name, ...) &kSig_##name,
84
85 static const FunctionSig* kSimdExprSigs[] = {
86 nullptr, FOREACH_SIMD_SIGNATURE(DECLARE_SIMD_SIG_ENTRY)};
87
88 static byte kSimpleExprSigTable[256];
89 static byte kSimpleAsmjsExprSigTable[256];
90 static byte kSimdExprSigTable[256];
91 static byte kAtomicExprSigTable[256];
92
93 // Initialize the signature table.
InitSigTables()94 static void InitSigTables() {
95 #define SET_SIG_TABLE(name, opcode, sig) \
96 kSimpleExprSigTable[opcode] = static_cast<int>(kSigEnum_##sig) + 1;
97 FOREACH_SIMPLE_OPCODE(SET_SIG_TABLE);
98 #undef SET_SIG_TABLE
99 #define SET_ASMJS_SIG_TABLE(name, opcode, sig) \
100 kSimpleAsmjsExprSigTable[opcode] = static_cast<int>(kSigEnum_##sig) + 1;
101 FOREACH_ASMJS_COMPAT_OPCODE(SET_ASMJS_SIG_TABLE);
102 #undef SET_ASMJS_SIG_TABLE
103 byte simd_index;
104 #define SET_SIG_TABLE(name, opcode, sig) \
105 simd_index = opcode & 0xff; \
106 kSimdExprSigTable[simd_index] = static_cast<int>(kSigEnum_##sig) + 1;
107 FOREACH_SIMD_0_OPERAND_OPCODE(SET_SIG_TABLE)
108 #undef SET_SIG_TABLE
109 byte atomic_index;
110 #define SET_ATOMIC_SIG_TABLE(name, opcode, sig) \
111 atomic_index = opcode & 0xff; \
112 kAtomicExprSigTable[atomic_index] = static_cast<int>(kSigEnum_##sig) + 1;
113 FOREACH_ATOMIC_OPCODE(SET_ATOMIC_SIG_TABLE)
114 #undef SET_ATOMIC_SIG_TABLE
115 }
116
117 class SigTable {
118 public:
SigTable()119 SigTable() {
120 // TODO(ahaas): Move {InitSigTable} into the class.
121 InitSigTables();
122 }
Signature(WasmOpcode opcode) const123 FunctionSig* Signature(WasmOpcode opcode) const {
124 return const_cast<FunctionSig*>(
125 kSimpleExprSigs[kSimpleExprSigTable[static_cast<byte>(opcode)]]);
126 }
AsmjsSignature(WasmOpcode opcode) const127 FunctionSig* AsmjsSignature(WasmOpcode opcode) const {
128 return const_cast<FunctionSig*>(
129 kSimpleExprSigs[kSimpleAsmjsExprSigTable[static_cast<byte>(opcode)]]);
130 }
SimdSignature(WasmOpcode opcode) const131 FunctionSig* SimdSignature(WasmOpcode opcode) const {
132 return const_cast<FunctionSig*>(
133 kSimdExprSigs[kSimdExprSigTable[static_cast<byte>(opcode & 0xff)]]);
134 }
AtomicSignature(WasmOpcode opcode) const135 FunctionSig* AtomicSignature(WasmOpcode opcode) const {
136 return const_cast<FunctionSig*>(
137 kSimpleExprSigs[kAtomicExprSigTable[static_cast<byte>(opcode & 0xff)]]);
138 }
139 };
140
141 static base::LazyInstance<SigTable>::type sig_table = LAZY_INSTANCE_INITIALIZER;
142
Signature(WasmOpcode opcode)143 FunctionSig* WasmOpcodes::Signature(WasmOpcode opcode) {
144 if (opcode >> 8 == kSimdPrefix) {
145 return sig_table.Get().SimdSignature(opcode);
146 } else {
147 return sig_table.Get().Signature(opcode);
148 }
149 }
150
AsmjsSignature(WasmOpcode opcode)151 FunctionSig* WasmOpcodes::AsmjsSignature(WasmOpcode opcode) {
152 return sig_table.Get().AsmjsSignature(opcode);
153 }
154
AtomicSignature(WasmOpcode opcode)155 FunctionSig* WasmOpcodes::AtomicSignature(WasmOpcode opcode) {
156 return sig_table.Get().AtomicSignature(opcode);
157 }
158
159 // TODO(titzer): pull WASM_64 up to a common header.
160 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
161 #define WASM_64 1
162 #else
163 #define WASM_64 0
164 #endif
165
TrapReasonToMessageId(TrapReason reason)166 int WasmOpcodes::TrapReasonToMessageId(TrapReason reason) {
167 switch (reason) {
168 #define TRAPREASON_TO_MESSAGE(name) \
169 case k##name: \
170 return MessageTemplate::kWasm##name;
171 FOREACH_WASM_TRAPREASON(TRAPREASON_TO_MESSAGE)
172 #undef TRAPREASON_TO_MESSAGE
173 default:
174 return MessageTemplate::kNone;
175 }
176 }
177
TrapReasonMessage(TrapReason reason)178 const char* WasmOpcodes::TrapReasonMessage(TrapReason reason) {
179 return MessageTemplate::TemplateString(TrapReasonToMessageId(reason));
180 }
181 } // namespace wasm
182 } // namespace internal
183 } // namespace v8
184