summaryrefslogtreecommitdiffstats
path: root/third_party/wasm2c/include/wabt/opcode.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/wasm2c/include/wabt/opcode.h')
-rw-r--r--third_party/wasm2c/include/wabt/opcode.h172
1 files changed, 172 insertions, 0 deletions
diff --git a/third_party/wasm2c/include/wabt/opcode.h b/third_party/wasm2c/include/wabt/opcode.h
new file mode 100644
index 0000000000..a7c7b2495a
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/opcode.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2017 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_H_
+#define WABT_OPCODE_H_
+
+#include <vector>
+
+#include "wabt/common.h"
+#include "wabt/leb128.h"
+#include "wabt/opcode-code-table.h"
+
+namespace wabt {
+
+class Features;
+
+struct Opcode {
+ // Opcode enumerations.
+ //
+ // NOTE: this enum does not match the binary encoding.
+ //
+ enum Enum : uint32_t {
+#define WABT_OPCODE(rtype, type1, type2, type3, mem_size, prefix, code, Name, \
+ text, decomp) \
+ Name,
+#include "wabt/opcode.def"
+#undef WABT_OPCODE
+ Invalid,
+ };
+
+// Static opcode objects.
+#define WABT_OPCODE(rtype, type1, type2, type3, mem_size, prefix, code, Name, \
+ text, decomp) \
+ static Opcode Name##_Opcode;
+#include "wabt/opcode.def"
+#undef WABT_OPCODE
+
+ Opcode() = default; // Provided so Opcode can be member of a union.
+ Opcode(Enum e) : enum_(e) {}
+ operator Enum() const { return enum_; }
+
+ static Opcode FromCode(uint32_t);
+ static Opcode FromCode(uint8_t prefix, uint32_t code);
+ bool HasPrefix() const { return GetInfo().prefix != 0; }
+ uint8_t GetPrefix() const { return GetInfo().prefix; }
+ uint32_t GetCode() const { return GetInfo().code; }
+ size_t GetLength() const { return GetBytes().size(); }
+ const char* GetName() const { return GetInfo().name; }
+ const char* GetDecomp() const {
+ return *GetInfo().decomp ? GetInfo().decomp : GetInfo().name;
+ }
+ Type GetResultType() const { return GetInfo().result_type; }
+ Type GetParamType1() const { return GetInfo().param_types[0]; }
+ Type GetParamType2() const { return GetInfo().param_types[1]; }
+ Type GetParamType3() const { return GetInfo().param_types[2]; }
+ Type GetParamType(int n) const { return GetInfo().param_types[n - 1]; }
+ Address GetMemorySize() const { return GetInfo().memory_size; }
+
+ // Get the byte sequence for this opcode, including prefix.
+ std::vector<uint8_t> GetBytes() const;
+
+ // Get the lane count of an extract/replace simd op.
+ uint32_t GetSimdLaneCount() const;
+
+ // Return 1 if |alignment| matches the alignment of |opcode|, or if
+ // |alignment| is WABT_USE_NATURAL_ALIGNMENT.
+ bool IsNaturallyAligned(Address alignment) const;
+
+ // If |alignment| is WABT_USE_NATURAL_ALIGNMENT, return the alignment of
+ // |opcode|, else return |alignment|.
+ Address GetAlignment(Address alignment) const;
+
+ static bool IsPrefixByte(uint8_t byte) {
+ return byte == kMathPrefix || byte == kThreadsPrefix || byte == kSimdPrefix;
+ }
+
+ bool IsEnabled(const Features& features) const;
+ bool IsInvalid() const { return enum_ >= Invalid; }
+
+ private:
+ static constexpr uint32_t kMathPrefix = 0xfc;
+ static constexpr uint32_t kThreadsPrefix = 0xfe;
+ static constexpr uint32_t kSimdPrefix = 0xfd;
+
+ struct Info {
+ const char* name;
+ const char* decomp;
+ Type result_type;
+ Type param_types[3];
+ Address memory_size;
+ uint8_t prefix;
+ uint32_t code;
+ uint32_t prefix_code; // See PrefixCode below. Used for fast lookup.
+ };
+
+ static uint32_t PrefixCode(uint8_t prefix, uint32_t code) {
+ if (code >= (1 << MAX_OPCODE_BITS)) {
+ // Clamp to (2^bits - 1), since we know that it is an invalid code.
+ code = (1 << MAX_OPCODE_BITS) - 1;
+ }
+ return (prefix << MAX_OPCODE_BITS) | code;
+ }
+
+ // The Opcode struct only stores an enumeration (Opcode::Enum) of all valid
+ // opcodes, densely packed. We want to be able to store invalid opcodes as
+ // well, for display to the user. To encode these, we use PrefixCode() to
+ // generate a uint32_t of the prefix/code pair, then negate the value so it
+ // doesn't overlap with the valid enum values. The negation is done using
+ // `~code + 1` since prefix_code is unsigned, and MSVC warns if you use - on
+ // an unsigned value.
+ //
+ // | 0 | Opcode::Invalid | INT32_MAX+1 UINT32_MAX |
+ // |---------------|-------------------------|---------------------------|
+ // | valid opcodes | unused space | invalid opcodes |
+ //
+ static Enum EncodeInvalidOpcode(uint32_t prefix_code) {
+ Enum result = static_cast<Enum>(~prefix_code + 1);
+ assert(result >= Invalid);
+ return result;
+ }
+
+ static void DecodeInvalidOpcode(Enum e,
+ uint8_t* out_prefix,
+ uint32_t* out_code) {
+ uint32_t prefix_code = ~static_cast<uint32_t>(e) + 1;
+ *out_prefix = prefix_code >> MAX_OPCODE_BITS;
+ *out_code = prefix_code & 0xff;
+ }
+
+ Info GetInfo() const;
+ static Info infos_[];
+
+ 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_