diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binary-reader-interp.cc | 9 | ||||
-rw-r--r-- | src/config.h.in | 6 | ||||
-rw-r--r-- | src/interp.cc | 13 | ||||
-rw-r--r-- | src/opcode-code-table.c | 41 | ||||
-rw-r--r-- | src/opcode-code-table.h | 38 | ||||
-rw-r--r-- | src/opcode.cc | 36 | ||||
-rw-r--r-- | src/opcode.h | 23 |
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_ |