summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binary-reader-interp.cc9
-rw-r--r--src/config.h.in6
-rw-r--r--src/interp.cc13
-rw-r--r--src/opcode-code-table.c41
-rw-r--r--src/opcode-code-table.h38
-rw-r--r--src/opcode.cc36
-rw-r--r--src/opcode.h23
7 files changed, 115 insertions, 51 deletions
diff --git a/src/binary-reader-interp.cc b/src/binary-reader-interp.cc
index 77941447..cfc32dba 100644
--- a/src/binary-reader-interp.cc
+++ b/src/binary-reader-interp.cc
@@ -422,14 +422,7 @@ wabt::Result BinaryReaderInterp::EmitData(const void* data,
}
wabt::Result BinaryReaderInterp::EmitOpcode(Opcode opcode) {
- if (opcode.HasPrefix()) {
- CHECK_RESULT(EmitI8(opcode.GetPrefix()));
- }
-
- // Assume opcode codes are all 1 byte for now (excluding the prefix).
- uint32_t code = opcode.GetCode();
- assert(code < 256);
- return EmitI8(code);
+ return EmitI32(static_cast<uint32_t>(opcode));
}
wabt::Result BinaryReaderInterp::EmitI8(uint8_t value) {
diff --git a/src/config.h.in b/src/config.h.in
index 9cff0b40..deb5c12f 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -98,7 +98,7 @@
#elif COMPILER_IS_MSVC
#include <intrin.h>
-#include <cstring>
+#include <string.h>
#define WABT_UNUSED
#define WABT_WARN_UNUSED
@@ -116,6 +116,8 @@
#endif
+#ifdef __cplusplus
+
namespace wabt {
#if COMPILER_IS_CLANG || COMPILER_IS_GNU
@@ -326,4 +328,6 @@ __inline float wabt_convert_uint64_to_float(uint64_t x) {
}
#endif
+#endif // __cplusplus
+
#endif /* WABT_CONFIG_H_ */
diff --git a/src/interp.cc b/src/interp.cc
index 60641485..c310e590 100644
--- a/src/interp.cc
+++ b/src/interp.cc
@@ -762,17 +762,8 @@ inline v128 ReadV128(const uint8_t** pc) {
}
inline Opcode ReadOpcode(const uint8_t** pc) {
- uint8_t value = ReadU8(pc);
- if (Opcode::IsPrefixByte(value)) {
- // For now, assume all instructions are encoded with just one extra byte
- // so we don't have to decode LEB128 here.
- uint32_t code = ReadU8(pc);
- return Opcode::FromCode(value, code);
- } else {
- // TODO(binji): Optimize if needed; Opcode::FromCode does a log2(n) lookup
- // from the encoding.
- return Opcode::FromCode(value);
- }
+ uint32_t value = ReadU32(pc);
+ return Opcode(static_cast<Opcode::Enum>(value));
}
inline void read_table_entry_at(const uint8_t* pc,
diff --git a/src/opcode-code-table.c b/src/opcode-code-table.c
new file mode 100644
index 00000000..f830e34b
--- /dev/null
+++ b/src/opcode-code-table.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2018 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/opcode-code-table.h"
+
+#include "config.h"
+
+#include <stdint.h>
+
+typedef enum WabtOpcodeEnum {
+#define WABT_OPCODE(rtype, type1, type2, type3, mem_size, prefix, code, Name, \
+ text) \
+ Name,
+#include "opcode.def"
+#undef WABT_OPCODE
+ Invalid,
+} WabtOpcodeEnum;
+
+WABT_STATIC_ASSERT(Invalid <= WABT_OPCODE_CODE_TABLE_SIZE);
+
+/* The array index calculated below must match the one in Opcode::FromCode. */
+uint32_t WabtOpcodeCodeTable[WABT_OPCODE_CODE_TABLE_SIZE] = {
+#define WABT_OPCODE(rtype, type1, type2, type3, mem_size, prefix, code, Name, \
+ text) \
+ [(prefix << 8) + code] = Name,
+#include "opcode.def"
+#undef WABT_OPCODE
+};
diff --git a/src/opcode-code-table.h b/src/opcode-code-table.h
new file mode 100644
index 00000000..b223e161
--- /dev/null
+++ b/src/opcode-code-table.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2018 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WABT_OPCODE_CODE_TABLE_H_
+#define WABT_OPCODE_CODE_TABLE_H_
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define WABT_OPCODE_CODE_TABLE_SIZE 65536
+
+/* This structure is defined in C because C++ doesn't (yet) allow you to use
+ * designated array initializers, i.e. [10] = {foo}.
+ */
+extern uint32_t WabtOpcodeCodeTable[WABT_OPCODE_CODE_TABLE_SIZE];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* WABT_OPCODE_CODE_TABLE_H_ */
diff --git a/src/opcode.cc b/src/opcode.cc
index 8a93f645..44dddfde 100644
--- a/src/opcode.cc
+++ b/src/opcode.cc
@@ -16,8 +16,6 @@
#include "src/opcode.h"
-#include <algorithm>
-
#include "src/feature.h"
namespace wabt {
@@ -31,6 +29,8 @@ Opcode::Info Opcode::infos_[] = {
prefix, code, PrefixCode(prefix, code)},
#include "src/opcode.def"
#undef WABT_OPCODE
+
+ {"<invalid>", Type::Void, Type::Void, Type::Void, Type::Void, 0, 0, 0, 0},
};
#define WABT_OPCODE(rtype, type1, type2, type3, mem_size, prefix, code, Name, \
@@ -39,40 +39,14 @@ Opcode::Info Opcode::infos_[] = {
#include "src/opcode.def"
#undef WABT_OPCODE
-// static
-Opcode Opcode::FromCode(uint32_t code) {
- return FromCode(0, code);
-}
-
-// static
-Opcode Opcode::FromCode(uint8_t prefix, uint32_t code) {
- uint32_t prefix_code = PrefixCode(prefix, code);
- auto begin = infos_;
- auto end = infos_ + WABT_ARRAY_SIZE(infos_);
- auto iter = std::lower_bound(begin, end, prefix_code,
- [](const Info& info, uint32_t prefix_code) {
- return info.prefix_code < prefix_code;
- });
- if (iter == end || iter->prefix_code != prefix_code) {
- return Opcode(EncodeInvalidOpcode(prefix_code));
- }
-
- return Opcode(static_cast<Enum>(iter - infos_));
-}
-
Opcode::Info Opcode::GetInfo() const {
if (enum_ < Invalid) {
return infos_[enum_];
}
- uint8_t prefix;
- uint32_t code;
- DecodeInvalidOpcode(enum_, &prefix, &code);
- const Info invalid_info = {
- "<invalid>", Type::Void, Type::Void,
- Type::Void, Type::Void, 0,
- prefix, code, PrefixCode(prefix, code),
- };
+ Info invalid_info = infos_[Opcode::Invalid];
+ DecodeInvalidOpcode(enum_, &invalid_info.prefix, &invalid_info.code);
+ invalid_info.prefix_code = PrefixCode(invalid_info.prefix, invalid_info.code);
return invalid_info;
}
diff --git a/src/opcode.h b/src/opcode.h
index c7dae08a..2a4d7d74 100644
--- a/src/opcode.h
+++ b/src/opcode.h
@@ -18,6 +18,7 @@
#define WABT_OPCODE_H_
#include "src/common.h"
+#include "src/opcode-code-table.h"
namespace wabt {
@@ -134,6 +135,28 @@ struct Opcode {
Enum enum_;
};
+// static
+inline Opcode Opcode::FromCode(uint32_t code) {
+ return FromCode(0, code);
+}
+
+// static
+inline Opcode Opcode::FromCode(uint8_t prefix, uint32_t code) {
+ uint32_t prefix_code = PrefixCode(prefix, code);
+
+ if (WABT_LIKELY(prefix_code < WABT_ARRAY_SIZE(WabtOpcodeCodeTable))) {
+ uint32_t value = WabtOpcodeCodeTable[prefix_code];
+ // The default value in the table is 0. That's a valid value, but only if
+ // the code is 0 (for nop).
+ if (WABT_LIKELY(value != 0 || code == 0)) {
+ return Opcode(static_cast<Enum>(value));
+ }
+ }
+
+ return Opcode(EncodeInvalidOpcode(prefix_code));
+}
+
+
} // namespace wabt
#endif // WABT_OPCODE_H_