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
9namespace v8 {
10namespace internal {
11namespace wasm {
12
13typedef Signature<LocalType> FunctionSig;
14
15const 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
28const 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
41std::ostream& operator<<(std::ostream& os, const FunctionSig& sig) {
42  if (sig.return_count() == 0) os << "v";
43  for (size_t i = 0; i < sig.return_count(); ++i) {
44    os << WasmOpcodes::ShortNameOf(sig.GetReturn(i));
45  }
46  os << "_";
47  if (sig.parameter_count() == 0) os << "v";
48  for (size_t i = 0; i < sig.parameter_count(); ++i) {
49    os << WasmOpcodes::ShortNameOf(sig.GetParam(i));
50  }
51  return os;
52}
53
54#define DECLARE_SIG_ENUM(name, ...) kSigEnum_##name,
55
56enum WasmOpcodeSig { FOREACH_SIGNATURE(DECLARE_SIG_ENUM) };
57
58// TODO(titzer): not static-initializer safe. Wrap in LazyInstance.
59#define DECLARE_SIG(name, ...)                      \
60  static LocalType kTypes_##name[] = {__VA_ARGS__}; \
61  static const FunctionSig kSig_##name(             \
62      1, static_cast<int>(arraysize(kTypes_##name)) - 1, kTypes_##name);
63
64FOREACH_SIGNATURE(DECLARE_SIG)
65
66#define DECLARE_SIG_ENTRY(name, ...) &kSig_##name,
67
68static const FunctionSig* kSimpleExprSigs[] = {
69    nullptr, FOREACH_SIGNATURE(DECLARE_SIG_ENTRY)};
70
71static byte kSimpleExprSigTable[256];
72
73// Initialize the signature table.
74static void InitSigTable() {
75#define SET_SIG_TABLE(name, opcode, sig) \
76  kSimpleExprSigTable[opcode] = static_cast<int>(kSigEnum_##sig) + 1;
77  FOREACH_SIMPLE_OPCODE(SET_SIG_TABLE);
78  FOREACH_ASMJS_COMPAT_OPCODE(SET_SIG_TABLE);
79#undef SET_SIG_TABLE
80}
81
82class SigTable {
83 public:
84  SigTable() {
85    // TODO(ahaas): Move {InitSigTable} into the class.
86    InitSigTable();
87  }
88  FunctionSig* Signature(WasmOpcode opcode) const {
89    return const_cast<FunctionSig*>(
90        kSimpleExprSigs[kSimpleExprSigTable[static_cast<byte>(opcode)]]);
91  }
92};
93
94static base::LazyInstance<SigTable>::type sig_table = LAZY_INSTANCE_INITIALIZER;
95
96FunctionSig* WasmOpcodes::Signature(WasmOpcode opcode) {
97  return sig_table.Get().Signature(opcode);
98}
99
100// TODO(titzer): pull WASM_64 up to a common header.
101#if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
102#define WASM_64 1
103#else
104#define WASM_64 0
105#endif
106
107int WasmOpcodes::TrapReasonToMessageId(TrapReason reason) {
108  switch (reason) {
109#define TRAPREASON_TO_MESSAGE(name) \
110  case k##name:                     \
111    return MessageTemplate::kWasm##name;
112    FOREACH_WASM_TRAPREASON(TRAPREASON_TO_MESSAGE)
113#undef TRAPREASON_TO_MESSAGE
114    default:
115      return MessageTemplate::kNone;
116  }
117}
118
119const char* WasmOpcodes::TrapReasonMessage(TrapReason reason) {
120  return MessageTemplate::TemplateString(TrapReasonToMessageId(reason));
121}
122}  // namespace wasm
123}  // namespace internal
124}  // namespace v8
125