summaryrefslogtreecommitdiffstats
path: root/third_party/wasm2c/src/binary-reader-opcnt.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/wasm2c/src/binary-reader-opcnt.cc')
-rw-r--r--third_party/wasm2c/src/binary-reader-opcnt.cc314
1 files changed, 314 insertions, 0 deletions
diff --git a/third_party/wasm2c/src/binary-reader-opcnt.cc b/third_party/wasm2c/src/binary-reader-opcnt.cc
new file mode 100644
index 0000000000..3177dbb7eb
--- /dev/null
+++ b/third_party/wasm2c/src/binary-reader-opcnt.cc
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2016 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 "wabt/binary-reader-opcnt.h"
+
+#include <cassert>
+#include <cinttypes>
+#include <cstdarg>
+#include <cstdint>
+#include <cstdio>
+
+#include "wabt/binary-reader-nop.h"
+#include "wabt/common.h"
+#include "wabt/literal.h"
+#include "wabt/stream.h"
+
+namespace wabt {
+
+OpcodeInfo::OpcodeInfo(Opcode opcode, Kind kind)
+ : opcode_(opcode), kind_(kind) {}
+
+template <typename T>
+OpcodeInfo::OpcodeInfo(Opcode opcode, Kind kind, T* data, size_t count)
+ : OpcodeInfo(opcode, kind) {
+ if (count > 0) {
+ data_.resize(sizeof(T) * count);
+ memcpy(data_.data(), data, data_.size());
+ }
+}
+
+template <typename T>
+OpcodeInfo::OpcodeInfo(Opcode opcode, Kind kind, T* data, size_t count, T extra)
+ : OpcodeInfo(opcode, kind, data, count) {
+ data_.resize(data_.size() + sizeof(T));
+ memcpy(data_.data() + data_.size() - sizeof(T), &extra, sizeof(T));
+}
+
+template <typename T>
+std::pair<const T*, size_t> OpcodeInfo::GetDataArray() const {
+ if (data_.empty()) {
+ return std::pair<const T*, size_t>(nullptr, 0);
+ }
+
+ assert(data_.size() % sizeof(T) == 0);
+ return std::make_pair(reinterpret_cast<const T*>(data_.data()),
+ data_.size() / sizeof(T));
+}
+
+template <typename T>
+const T* OpcodeInfo::GetData(size_t expected_size) const {
+ auto [data, size] = GetDataArray<T>();
+ assert(size == expected_size);
+ return data;
+}
+
+template <typename T, typename F>
+void OpcodeInfo::WriteArray(Stream& stream, F&& write_func) {
+ auto [data, size] = GetDataArray<T>();
+ for (size_t i = 0; i < size; ++i) {
+ // Write an initial space (to separate from the opcode name) first, then
+ // comma-separate.
+ stream.Writef("%s", i == 0 ? " " : ", ");
+ write_func(data[i]);
+ }
+}
+
+void OpcodeInfo::Write(Stream& stream) {
+ stream.Writef("%s", opcode_.GetName());
+
+ switch (kind_) {
+ case Kind::Bare:
+ break;
+
+ case Kind::Uint32:
+ stream.Writef(" %u (0x%x)", *GetData<uint32_t>(), *GetData<uint32_t>());
+ break;
+
+ case Kind::Uint64:
+ stream.Writef(" %" PRIu64 " (0x%" PRIx64 ")", *GetData<uint64_t>(),
+ *GetData<uint64_t>());
+ break;
+
+ case Kind::Index:
+ stream.Writef(" %" PRIindex, *GetData<Index>());
+ break;
+
+ case Kind::Float32: {
+ stream.Writef(" %g", *GetData<float>());
+ char buffer[WABT_MAX_FLOAT_HEX + 1];
+ WriteFloatHex(buffer, sizeof(buffer), *GetData<uint32_t>());
+ stream.Writef(" (%s)", buffer);
+ break;
+ }
+
+ case Kind::Float64: {
+ stream.Writef(" %g", *GetData<double>());
+ char buffer[WABT_MAX_DOUBLE_HEX + 1];
+ WriteDoubleHex(buffer, sizeof(buffer), *GetData<uint64_t>());
+ stream.Writef(" (%s)", buffer);
+ break;
+ }
+
+ case Kind::V128: {
+ auto data = *GetData<v128>();
+ auto l0 = data.u32(0);
+ auto l1 = data.u32(1);
+ auto l2 = data.u32(2);
+ auto l3 = data.u32(3);
+ stream.Writef(" %u %u %u %u (0x%x 0x%x 0x%x 0x%x)", l0, l1, l2, l3, l0,
+ l1, l2, l3);
+ break;
+ }
+
+ case Kind::Uint32Uint32:
+ case Kind::Uint32Uint32Uint32:
+ case Kind::Uint32Uint32Uint32Uint32:
+ WriteArray<uint32_t>(
+ stream, [&stream](uint32_t value) { stream.Writef("%u", value); });
+ break;
+
+ case Kind::BlockSig: {
+ auto type = *GetData<Type>();
+ if (type.IsIndex()) {
+ stream.Writef(" type:%d", type.GetIndex());
+ } else if (type != Type::Void) {
+ stream.Writef(" %s", type.GetName().c_str());
+ }
+ break;
+ }
+
+ case Kind::BrTable: {
+ WriteArray<Index>(stream, [&stream](Index index) {
+ stream.Writef("%" PRIindex, index);
+ });
+ break;
+ }
+ }
+}
+
+bool operator==(const OpcodeInfo& lhs, const OpcodeInfo& rhs) {
+ return lhs.opcode_ == rhs.opcode_ && lhs.kind_ == rhs.kind_ &&
+ lhs.data_ == rhs.data_;
+}
+
+bool operator!=(const OpcodeInfo& lhs, const OpcodeInfo& rhs) {
+ return !(lhs == rhs);
+}
+
+bool operator<(const OpcodeInfo& lhs, const OpcodeInfo& rhs) {
+ if (lhs.opcode_ < rhs.opcode_) {
+ return true;
+ }
+ if (lhs.opcode_ > rhs.opcode_) {
+ return false;
+ }
+ if (lhs.kind_ < rhs.kind_) {
+ return true;
+ }
+ if (lhs.kind_ > rhs.kind_) {
+ return false;
+ }
+ if (lhs.data_ < rhs.data_) {
+ return true;
+ }
+ if (lhs.data_ > rhs.data_) {
+ return false;
+ }
+ return false;
+}
+
+bool operator<=(const OpcodeInfo& lhs, const OpcodeInfo& rhs) {
+ return lhs < rhs || lhs == rhs;
+}
+
+bool operator>(const OpcodeInfo& lhs, const OpcodeInfo& rhs) {
+ return !(lhs <= rhs);
+}
+
+bool operator>=(const OpcodeInfo& lhs, const OpcodeInfo& rhs) {
+ return !(lhs < rhs);
+}
+
+namespace {
+
+class BinaryReaderOpcnt : public BinaryReaderNop {
+ public:
+ explicit BinaryReaderOpcnt(OpcodeInfoCounts* counts);
+
+ Result OnOpcode(Opcode opcode) override;
+ Result OnOpcodeBare() override;
+ Result OnOpcodeUint32(uint32_t value) override;
+ Result OnOpcodeIndex(Index value) override;
+ Result OnOpcodeUint32Uint32(uint32_t value, uint32_t value2) override;
+ Result OnOpcodeUint32Uint32Uint32(uint32_t value,
+ uint32_t value2,
+ uint32_t value3) override;
+ Result OnOpcodeUint64(uint64_t value) override;
+ Result OnOpcodeF32(uint32_t value) override;
+ Result OnOpcodeF64(uint64_t value) override;
+ Result OnOpcodeV128(v128 value) override;
+ Result OnOpcodeBlockSig(Type sig_type) override;
+ Result OnBrTableExpr(Index num_targets,
+ Index* target_depths,
+ Index default_target_depth) override;
+ Result OnEndExpr() override;
+
+ private:
+ template <typename... Args>
+ Result Emplace(Args&&... args);
+
+ OpcodeInfoCounts* opcode_counts_;
+ Opcode current_opcode_;
+};
+
+template <typename... Args>
+Result BinaryReaderOpcnt::Emplace(Args&&... args) {
+ auto pair = opcode_counts_->emplace(
+ std::piecewise_construct, std::make_tuple(std::forward<Args>(args)...),
+ std::make_tuple(0));
+
+ auto& count = pair.first->second;
+ count++;
+ return Result::Ok;
+}
+
+BinaryReaderOpcnt::BinaryReaderOpcnt(OpcodeInfoCounts* counts)
+ : opcode_counts_(counts) {}
+
+Result BinaryReaderOpcnt::OnOpcode(Opcode opcode) {
+ current_opcode_ = opcode;
+ return Result::Ok;
+}
+
+Result BinaryReaderOpcnt::OnOpcodeBare() {
+ return Emplace(current_opcode_, OpcodeInfo::Kind::Bare);
+}
+
+Result BinaryReaderOpcnt::OnOpcodeUint32(uint32_t value) {
+ return Emplace(current_opcode_, OpcodeInfo::Kind::Uint32, &value);
+}
+
+Result BinaryReaderOpcnt::OnOpcodeIndex(Index value) {
+ return Emplace(current_opcode_, OpcodeInfo::Kind::Index, &value);
+}
+
+Result BinaryReaderOpcnt::OnOpcodeUint32Uint32(uint32_t value0,
+ uint32_t value1) {
+ uint32_t array[2] = {value0, value1};
+ return Emplace(current_opcode_, OpcodeInfo::Kind::Uint32Uint32, array, 2);
+}
+
+Result BinaryReaderOpcnt::OnOpcodeUint32Uint32Uint32(uint32_t value0,
+ uint32_t value1,
+ uint32_t value2) {
+ uint32_t array[3] = {value0, value1, value2};
+ return Emplace(current_opcode_, OpcodeInfo::Kind::Uint32Uint32Uint32, array,
+ 3);
+}
+
+Result BinaryReaderOpcnt::OnOpcodeUint64(uint64_t value) {
+ return Emplace(current_opcode_, OpcodeInfo::Kind::Uint64, &value);
+}
+
+Result BinaryReaderOpcnt::OnOpcodeF32(uint32_t value) {
+ return Emplace(current_opcode_, OpcodeInfo::Kind::Float32, &value);
+}
+
+Result BinaryReaderOpcnt::OnOpcodeF64(uint64_t value) {
+ return Emplace(current_opcode_, OpcodeInfo::Kind::Float64, &value);
+}
+
+Result BinaryReaderOpcnt::OnOpcodeV128(v128 value) {
+ return Emplace(current_opcode_, OpcodeInfo::Kind::V128, &value);
+}
+
+Result BinaryReaderOpcnt::OnOpcodeBlockSig(Type sig_type) {
+ return Emplace(current_opcode_, OpcodeInfo::Kind::BlockSig, &sig_type);
+}
+
+Result BinaryReaderOpcnt::OnBrTableExpr(Index num_targets,
+ Index* target_depths,
+ Index default_target_depth) {
+ return Emplace(current_opcode_, OpcodeInfo::Kind::BrTable, target_depths,
+ num_targets, default_target_depth);
+}
+
+Result BinaryReaderOpcnt::OnEndExpr() {
+ return Emplace(Opcode::End, OpcodeInfo::Kind::Bare);
+}
+
+} // end anonymous namespace
+
+Result ReadBinaryOpcnt(const void* data,
+ size_t size,
+ const ReadBinaryOptions& options,
+ OpcodeInfoCounts* counts) {
+ BinaryReaderOpcnt reader(counts);
+ return ReadBinary(data, size, &reader, options);
+}
+
+} // namespace wabt