aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/hyperscan/src/rose/rose_build_instructions.h
diff options
context:
space:
mode:
authorIvan Blinkov <ivan@blinkov.ru>2022-02-10 16:47:11 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:47:11 +0300
commit5b283123c882433dafbaf6b338adeea16c1a0ea0 (patch)
tree339adc63bce23800021202ae4a8328a843dc447a /contrib/libs/hyperscan/src/rose/rose_build_instructions.h
parent1aeb9a455974457866f78722ad98114bafc84e8a (diff)
downloadydb-5b283123c882433dafbaf6b338adeea16c1a0ea0.tar.gz
Restoring authorship annotation for Ivan Blinkov <ivan@blinkov.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/hyperscan/src/rose/rose_build_instructions.h')
-rw-r--r--contrib/libs/hyperscan/src/rose/rose_build_instructions.h4308
1 files changed, 2154 insertions, 2154 deletions
diff --git a/contrib/libs/hyperscan/src/rose/rose_build_instructions.h b/contrib/libs/hyperscan/src/rose/rose_build_instructions.h
index ee2acddd48..f18f4a4715 100644
--- a/contrib/libs/hyperscan/src/rose/rose_build_instructions.h
+++ b/contrib/libs/hyperscan/src/rose/rose_build_instructions.h
@@ -1,524 +1,524 @@
-/*
+/*
* Copyright (c) 2017-2020, Intel Corporation
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Intel Corporation nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** \file
- * \brief Concrete classes for interpreter instructions.
- *
- * Note: this header should only be included in files which need to deal with
- * the details of actual instructions. It is expected that most will only
- * require access to the RoseInstruction API exposed in rose_build_program.h
- */
-
-#ifndef ROSE_BUILD_INSTRUCTIONS_H
-#define ROSE_BUILD_INSTRUCTIONS_H
-
-#include "rose_build_lookaround.h"
-#include "rose_build_program.h"
-#include "util/hash.h"
-#include "util/verify_types.h"
-
-namespace ue2 {
-
-/**
- * \brief Abstract base class representing a single Rose instruction.
- */
-class RoseInstruction {
-public:
- virtual ~RoseInstruction();
-
- /** \brief Opcode used for the instruction in the bytecode. */
- virtual RoseInstructionCode code() const = 0;
-
- /**
- * \brief Simple hash used for program equivalence.
- *
- * Note that pointers (jumps, for example) should not be used when
- * calculating the hash: they will be converted to instruction offsets when
- * compared later.
- */
- virtual size_t hash() const = 0;
-
- /** \brief Length of the bytecode instruction in bytes. */
- virtual size_t byte_length() const = 0;
-
- using OffsetMap = std::unordered_map<const RoseInstruction *, u32>;
-
- /**
- * \brief Writes a concrete implementation of this instruction.
- *
- * Other data that this instruction depends on is written directly into the
- * blob, while the instruction structure itself (of size given by
- * the byte_length() function) is written to dest.
- */
- virtual void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const = 0;
-
- /**
- * \brief Update a target pointer.
- *
- * If this instruction contains any reference to the old target, replace it
- * with the new one.
- */
- virtual void update_target(const RoseInstruction *old_target,
- const RoseInstruction *new_target) = 0;
-
- /**
- * \brief True if these instructions are equivalent within their own
- * programs.
- *
- * Checks that any pointers to other instructions point to the same
- * offsets.
- */
- bool equiv(const RoseInstruction &other, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return equiv_impl(other, offsets, other_offsets);
- }
-
-private:
- virtual bool equiv_impl(const RoseInstruction &other,
- const OffsetMap &offsets,
- const OffsetMap &other_offsets) const = 0;
-};
-
-/**
- * \brief Templated implementation class to handle boring boilerplate code.
- */
-template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType>
-class RoseInstrBase : public RoseInstruction {
-protected:
- static constexpr RoseInstructionCode opcode = Opcode;
- using impl_type = ImplType;
-
-public:
- RoseInstructionCode code() const override { return opcode; }
-
- size_t byte_length() const override {
- return sizeof(impl_type);
- }
-
- /**
- * Note: this implementation simply zeroes the destination region and
- * writes in the correct opcode. This is sufficient for trivial
- * instructions, but instructions with data members will want to override
- * it.
- */
- void write(void *dest, RoseEngineBlob &,
- const RoseInstruction::OffsetMap &) const override {
- assert(dest != nullptr);
- assert(ISALIGNED_N(dest, ROSE_INSTR_MIN_ALIGN));
-
- impl_type *inst = static_cast<impl_type *>(dest);
- memset(inst, 0, sizeof(impl_type));
- inst->code = verify_u8(opcode);
- }
-
-private:
- bool equiv_impl(const RoseInstruction &other, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const override {
- const auto *ri_that = dynamic_cast<const RoseInstrType *>(&other);
- if (!ri_that) {
- return false;
- }
- const auto *ri_this = dynamic_cast<const RoseInstrType *>(this);
- assert(ri_this);
- return ri_this->equiv_to(*ri_that, offsets, other_offsets);
- }
-};
-
-template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType>
-constexpr RoseInstructionCode
- RoseInstrBase<Opcode, ImplType, RoseInstrType>::opcode;
-
-/**
- * \brief Refinement of RoseInstrBase to use for instructions that have
- * just a single target member, called "target".
- */
-template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType>
-class RoseInstrBaseOneTarget
- : public RoseInstrBase<Opcode, ImplType, RoseInstrType> {
-public:
- void update_target(const RoseInstruction *old_target,
- const RoseInstruction *new_target) override {
- RoseInstrType *ri = dynamic_cast<RoseInstrType *>(this);
- assert(ri);
- if (ri->target == old_target) {
- ri->target = new_target;
- }
- }
-};
-
-/**
- * \brief Refinement of RoseInstrBase to use for instructions that have no
- * targets.
- */
-template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType>
-class RoseInstrBaseNoTargets
- : public RoseInstrBase<Opcode, ImplType, RoseInstrType> {
-public:
- void update_target(const RoseInstruction *,
- const RoseInstruction *) override {}
-};
-
-/**
- * \brief Refinement of RoseInstrBaseNoTargets to use for instructions that
- * have no members at all, just an opcode.
- */
-template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType>
-class RoseInstrBaseTrivial
- : public RoseInstrBaseNoTargets<Opcode, ImplType, RoseInstrType> {
-public:
- virtual bool operator==(const RoseInstrType &) const { return true; }
-
- size_t hash() const override {
- return hash_all(Opcode);
- }
-
- bool equiv_to(const RoseInstrType &, const RoseInstruction::OffsetMap &,
- const RoseInstruction::OffsetMap &) const {
- return true;
- }
-};
-
-////
-//// Concrete implementation classes start here.
-////
-
-class RoseInstrAnchoredDelay
- : public RoseInstrBaseOneTarget<ROSE_INSTR_ANCHORED_DELAY,
- ROSE_STRUCT_ANCHORED_DELAY,
- RoseInstrAnchoredDelay> {
-public:
- rose_group groups;
- u32 anch_id;
- const RoseInstruction *target;
-
- RoseInstrAnchoredDelay(rose_group groups_in, u32 anch_id_in,
- const RoseInstruction *target_in)
- : groups(groups_in), anch_id(anch_id_in), target(target_in) {}
-
- bool operator==(const RoseInstrAnchoredDelay &ri) const {
- return groups == ri.groups && anch_id == ri.anch_id
- && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, groups, anch_id);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrAnchoredDelay &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return groups == ri.groups && anch_id == ri.anch_id
- && offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckLitEarly
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_LIT_EARLY,
- ROSE_STRUCT_CHECK_LIT_EARLY,
- RoseInstrCheckLitEarly> {
-public:
- u32 min_offset;
- const RoseInstruction *target;
-
- RoseInstrCheckLitEarly(u32 min_offset_in, const RoseInstruction *target_in)
- : min_offset(min_offset_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckLitEarly &ri) const {
- return min_offset == ri.min_offset && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, min_offset);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckLitEarly &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return min_offset == ri.min_offset &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckGroups
- : public RoseInstrBaseNoTargets<ROSE_INSTR_CHECK_GROUPS,
- ROSE_STRUCT_CHECK_GROUPS,
- RoseInstrCheckGroups> {
-public:
- rose_group groups;
-
- explicit RoseInstrCheckGroups(rose_group groups_in) : groups(groups_in) {}
-
- bool operator==(const RoseInstrCheckGroups &ri) const {
- return groups == ri.groups;
- }
-
- size_t hash() const override {
- return hash_all(opcode, groups);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckGroups &ri, const OffsetMap &,
- const OffsetMap &) const {
- return groups == ri.groups;
- }
-};
-
-class RoseInstrCheckOnlyEod
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_ONLY_EOD,
- ROSE_STRUCT_CHECK_ONLY_EOD,
- RoseInstrCheckOnlyEod> {
-public:
- const RoseInstruction *target;
-
- explicit RoseInstrCheckOnlyEod(const RoseInstruction *target_in)
- : target(target_in) {}
-
- bool operator==(const RoseInstrCheckOnlyEod &ri) const {
- return target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckOnlyEod &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckBounds
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_BOUNDS,
- ROSE_STRUCT_CHECK_BOUNDS,
- RoseInstrCheckBounds> {
-public:
- u64a min_bound;
- u64a max_bound;
- const RoseInstruction *target;
-
- RoseInstrCheckBounds(u64a min, u64a max, const RoseInstruction *target_in)
- : min_bound(min), max_bound(max), target(target_in) {}
-
- bool operator==(const RoseInstrCheckBounds &ri) const {
- return min_bound == ri.min_bound && max_bound == ri.max_bound &&
- target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, min_bound, max_bound);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckBounds &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return min_bound == ri.min_bound && max_bound == ri.max_bound &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckNotHandled
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_NOT_HANDLED,
- ROSE_STRUCT_CHECK_NOT_HANDLED,
- RoseInstrCheckNotHandled> {
-public:
- u32 key;
- const RoseInstruction *target;
-
- RoseInstrCheckNotHandled(u32 key_in, const RoseInstruction *target_in)
- : key(key_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckNotHandled &ri) const {
- return key == ri.key && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, key);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckNotHandled &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return key == ri.key &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckSingleLookaround
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SINGLE_LOOKAROUND,
- ROSE_STRUCT_CHECK_SINGLE_LOOKAROUND,
- RoseInstrCheckSingleLookaround> {
-public:
- s8 offset;
- CharReach reach;
- const RoseInstruction *target;
-
- RoseInstrCheckSingleLookaround(s8 offset_in, CharReach reach_in,
- const RoseInstruction *target_in)
- : offset(offset_in), reach(std::move(reach_in)), target(target_in) {}
-
- bool operator==(const RoseInstrCheckSingleLookaround &ri) const {
- return offset == ri.offset && reach == ri.reach && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, offset, reach);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckSingleLookaround &ri,
- const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return offset == ri.offset && reach == ri.reach &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckLookaround
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_LOOKAROUND,
- ROSE_STRUCT_CHECK_LOOKAROUND,
- RoseInstrCheckLookaround> {
-public:
- std::vector<LookEntry> look;
- const RoseInstruction *target;
-
- RoseInstrCheckLookaround(std::vector<LookEntry> look_in,
- const RoseInstruction *target_in)
- : look(std::move(look_in)), target(target_in) {}
-
- bool operator==(const RoseInstrCheckLookaround &ri) const {
- return look == ri.look && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, look);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckLookaround &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return look == ri.look
- && offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckMask
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MASK,
- ROSE_STRUCT_CHECK_MASK,
- RoseInstrCheckMask> {
-public:
- u64a and_mask;
- u64a cmp_mask;
- u64a neg_mask;
- s32 offset;
- const RoseInstruction *target;
-
- RoseInstrCheckMask(u64a and_mask_in, u64a cmp_mask_in, u64a neg_mask_in,
- s32 offset_in, const RoseInstruction *target_in)
- : and_mask(and_mask_in), cmp_mask(cmp_mask_in), neg_mask(neg_mask_in),
- offset(offset_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckMask &ri) const {
- return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask &&
- neg_mask == ri.neg_mask && offset == ri.offset &&
- target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, and_mask, cmp_mask, neg_mask, offset);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckMask &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask &&
- neg_mask == ri.neg_mask && offset == ri.offset &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckMask32
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MASK_32,
- ROSE_STRUCT_CHECK_MASK_32,
- RoseInstrCheckMask32> {
-public:
- std::array<u8, 32> and_mask;
- std::array<u8, 32> cmp_mask;
- u32 neg_mask;
- s32 offset;
- const RoseInstruction *target;
-
- RoseInstrCheckMask32(std::array<u8, 32> and_mask_in,
- std::array<u8, 32> cmp_mask_in, u32 neg_mask_in,
- s32 offset_in, const RoseInstruction *target_in)
- : and_mask(std::move(and_mask_in)), cmp_mask(std::move(cmp_mask_in)),
- neg_mask(neg_mask_in), offset(offset_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckMask32 &ri) const {
- return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask &&
- neg_mask == ri.neg_mask && offset == ri.offset &&
- target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, and_mask, cmp_mask, neg_mask, offset);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckMask32 &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask &&
- neg_mask == ri.neg_mask && offset == ri.offset &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** \file
+ * \brief Concrete classes for interpreter instructions.
+ *
+ * Note: this header should only be included in files which need to deal with
+ * the details of actual instructions. It is expected that most will only
+ * require access to the RoseInstruction API exposed in rose_build_program.h
+ */
+
+#ifndef ROSE_BUILD_INSTRUCTIONS_H
+#define ROSE_BUILD_INSTRUCTIONS_H
+
+#include "rose_build_lookaround.h"
+#include "rose_build_program.h"
+#include "util/hash.h"
+#include "util/verify_types.h"
+
+namespace ue2 {
+
+/**
+ * \brief Abstract base class representing a single Rose instruction.
+ */
+class RoseInstruction {
+public:
+ virtual ~RoseInstruction();
+
+ /** \brief Opcode used for the instruction in the bytecode. */
+ virtual RoseInstructionCode code() const = 0;
+
+ /**
+ * \brief Simple hash used for program equivalence.
+ *
+ * Note that pointers (jumps, for example) should not be used when
+ * calculating the hash: they will be converted to instruction offsets when
+ * compared later.
+ */
+ virtual size_t hash() const = 0;
+
+ /** \brief Length of the bytecode instruction in bytes. */
+ virtual size_t byte_length() const = 0;
+
+ using OffsetMap = std::unordered_map<const RoseInstruction *, u32>;
+
+ /**
+ * \brief Writes a concrete implementation of this instruction.
+ *
+ * Other data that this instruction depends on is written directly into the
+ * blob, while the instruction structure itself (of size given by
+ * the byte_length() function) is written to dest.
+ */
+ virtual void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const = 0;
+
+ /**
+ * \brief Update a target pointer.
+ *
+ * If this instruction contains any reference to the old target, replace it
+ * with the new one.
+ */
+ virtual void update_target(const RoseInstruction *old_target,
+ const RoseInstruction *new_target) = 0;
+
+ /**
+ * \brief True if these instructions are equivalent within their own
+ * programs.
+ *
+ * Checks that any pointers to other instructions point to the same
+ * offsets.
+ */
+ bool equiv(const RoseInstruction &other, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return equiv_impl(other, offsets, other_offsets);
+ }
+
+private:
+ virtual bool equiv_impl(const RoseInstruction &other,
+ const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const = 0;
+};
+
+/**
+ * \brief Templated implementation class to handle boring boilerplate code.
+ */
+template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType>
+class RoseInstrBase : public RoseInstruction {
+protected:
+ static constexpr RoseInstructionCode opcode = Opcode;
+ using impl_type = ImplType;
+
+public:
+ RoseInstructionCode code() const override { return opcode; }
+
+ size_t byte_length() const override {
+ return sizeof(impl_type);
+ }
+
+ /**
+ * Note: this implementation simply zeroes the destination region and
+ * writes in the correct opcode. This is sufficient for trivial
+ * instructions, but instructions with data members will want to override
+ * it.
+ */
+ void write(void *dest, RoseEngineBlob &,
+ const RoseInstruction::OffsetMap &) const override {
+ assert(dest != nullptr);
+ assert(ISALIGNED_N(dest, ROSE_INSTR_MIN_ALIGN));
+
+ impl_type *inst = static_cast<impl_type *>(dest);
+ memset(inst, 0, sizeof(impl_type));
+ inst->code = verify_u8(opcode);
+ }
+
+private:
+ bool equiv_impl(const RoseInstruction &other, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const override {
+ const auto *ri_that = dynamic_cast<const RoseInstrType *>(&other);
+ if (!ri_that) {
+ return false;
+ }
+ const auto *ri_this = dynamic_cast<const RoseInstrType *>(this);
+ assert(ri_this);
+ return ri_this->equiv_to(*ri_that, offsets, other_offsets);
+ }
+};
+
+template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType>
+constexpr RoseInstructionCode
+ RoseInstrBase<Opcode, ImplType, RoseInstrType>::opcode;
+
+/**
+ * \brief Refinement of RoseInstrBase to use for instructions that have
+ * just a single target member, called "target".
+ */
+template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType>
+class RoseInstrBaseOneTarget
+ : public RoseInstrBase<Opcode, ImplType, RoseInstrType> {
+public:
+ void update_target(const RoseInstruction *old_target,
+ const RoseInstruction *new_target) override {
+ RoseInstrType *ri = dynamic_cast<RoseInstrType *>(this);
+ assert(ri);
+ if (ri->target == old_target) {
+ ri->target = new_target;
+ }
+ }
+};
+
+/**
+ * \brief Refinement of RoseInstrBase to use for instructions that have no
+ * targets.
+ */
+template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType>
+class RoseInstrBaseNoTargets
+ : public RoseInstrBase<Opcode, ImplType, RoseInstrType> {
+public:
+ void update_target(const RoseInstruction *,
+ const RoseInstruction *) override {}
+};
+
+/**
+ * \brief Refinement of RoseInstrBaseNoTargets to use for instructions that
+ * have no members at all, just an opcode.
+ */
+template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType>
+class RoseInstrBaseTrivial
+ : public RoseInstrBaseNoTargets<Opcode, ImplType, RoseInstrType> {
+public:
+ virtual bool operator==(const RoseInstrType &) const { return true; }
+
+ size_t hash() const override {
+ return hash_all(Opcode);
+ }
+
+ bool equiv_to(const RoseInstrType &, const RoseInstruction::OffsetMap &,
+ const RoseInstruction::OffsetMap &) const {
+ return true;
+ }
+};
+
+////
+//// Concrete implementation classes start here.
+////
+
+class RoseInstrAnchoredDelay
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_ANCHORED_DELAY,
+ ROSE_STRUCT_ANCHORED_DELAY,
+ RoseInstrAnchoredDelay> {
+public:
+ rose_group groups;
+ u32 anch_id;
+ const RoseInstruction *target;
+
+ RoseInstrAnchoredDelay(rose_group groups_in, u32 anch_id_in,
+ const RoseInstruction *target_in)
+ : groups(groups_in), anch_id(anch_id_in), target(target_in) {}
+
+ bool operator==(const RoseInstrAnchoredDelay &ri) const {
+ return groups == ri.groups && anch_id == ri.anch_id
+ && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, groups, anch_id);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrAnchoredDelay &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return groups == ri.groups && anch_id == ri.anch_id
+ && offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckLitEarly
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_LIT_EARLY,
+ ROSE_STRUCT_CHECK_LIT_EARLY,
+ RoseInstrCheckLitEarly> {
+public:
+ u32 min_offset;
+ const RoseInstruction *target;
+
+ RoseInstrCheckLitEarly(u32 min_offset_in, const RoseInstruction *target_in)
+ : min_offset(min_offset_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckLitEarly &ri) const {
+ return min_offset == ri.min_offset && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, min_offset);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckLitEarly &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return min_offset == ri.min_offset &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckGroups
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_CHECK_GROUPS,
+ ROSE_STRUCT_CHECK_GROUPS,
+ RoseInstrCheckGroups> {
+public:
+ rose_group groups;
+
+ explicit RoseInstrCheckGroups(rose_group groups_in) : groups(groups_in) {}
+
+ bool operator==(const RoseInstrCheckGroups &ri) const {
+ return groups == ri.groups;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, groups);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckGroups &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return groups == ri.groups;
+ }
+};
+
+class RoseInstrCheckOnlyEod
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_ONLY_EOD,
+ ROSE_STRUCT_CHECK_ONLY_EOD,
+ RoseInstrCheckOnlyEod> {
+public:
+ const RoseInstruction *target;
+
+ explicit RoseInstrCheckOnlyEod(const RoseInstruction *target_in)
+ : target(target_in) {}
+
+ bool operator==(const RoseInstrCheckOnlyEod &ri) const {
+ return target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckOnlyEod &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckBounds
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_BOUNDS,
+ ROSE_STRUCT_CHECK_BOUNDS,
+ RoseInstrCheckBounds> {
+public:
+ u64a min_bound;
+ u64a max_bound;
+ const RoseInstruction *target;
+
+ RoseInstrCheckBounds(u64a min, u64a max, const RoseInstruction *target_in)
+ : min_bound(min), max_bound(max), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckBounds &ri) const {
+ return min_bound == ri.min_bound && max_bound == ri.max_bound &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, min_bound, max_bound);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckBounds &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return min_bound == ri.min_bound && max_bound == ri.max_bound &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckNotHandled
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_NOT_HANDLED,
+ ROSE_STRUCT_CHECK_NOT_HANDLED,
+ RoseInstrCheckNotHandled> {
+public:
+ u32 key;
+ const RoseInstruction *target;
+
+ RoseInstrCheckNotHandled(u32 key_in, const RoseInstruction *target_in)
+ : key(key_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckNotHandled &ri) const {
+ return key == ri.key && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, key);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckNotHandled &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return key == ri.key &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckSingleLookaround
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SINGLE_LOOKAROUND,
+ ROSE_STRUCT_CHECK_SINGLE_LOOKAROUND,
+ RoseInstrCheckSingleLookaround> {
+public:
+ s8 offset;
+ CharReach reach;
+ const RoseInstruction *target;
+
+ RoseInstrCheckSingleLookaround(s8 offset_in, CharReach reach_in,
+ const RoseInstruction *target_in)
+ : offset(offset_in), reach(std::move(reach_in)), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckSingleLookaround &ri) const {
+ return offset == ri.offset && reach == ri.reach && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, offset, reach);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckSingleLookaround &ri,
+ const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return offset == ri.offset && reach == ri.reach &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckLookaround
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_LOOKAROUND,
+ ROSE_STRUCT_CHECK_LOOKAROUND,
+ RoseInstrCheckLookaround> {
+public:
+ std::vector<LookEntry> look;
+ const RoseInstruction *target;
+
+ RoseInstrCheckLookaround(std::vector<LookEntry> look_in,
+ const RoseInstruction *target_in)
+ : look(std::move(look_in)), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckLookaround &ri) const {
+ return look == ri.look && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, look);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckLookaround &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return look == ri.look
+ && offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckMask
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MASK,
+ ROSE_STRUCT_CHECK_MASK,
+ RoseInstrCheckMask> {
+public:
+ u64a and_mask;
+ u64a cmp_mask;
+ u64a neg_mask;
+ s32 offset;
+ const RoseInstruction *target;
+
+ RoseInstrCheckMask(u64a and_mask_in, u64a cmp_mask_in, u64a neg_mask_in,
+ s32 offset_in, const RoseInstruction *target_in)
+ : and_mask(and_mask_in), cmp_mask(cmp_mask_in), neg_mask(neg_mask_in),
+ offset(offset_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckMask &ri) const {
+ return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask &&
+ neg_mask == ri.neg_mask && offset == ri.offset &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, and_mask, cmp_mask, neg_mask, offset);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckMask &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask &&
+ neg_mask == ri.neg_mask && offset == ri.offset &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckMask32
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MASK_32,
+ ROSE_STRUCT_CHECK_MASK_32,
+ RoseInstrCheckMask32> {
+public:
+ std::array<u8, 32> and_mask;
+ std::array<u8, 32> cmp_mask;
+ u32 neg_mask;
+ s32 offset;
+ const RoseInstruction *target;
+
+ RoseInstrCheckMask32(std::array<u8, 32> and_mask_in,
+ std::array<u8, 32> cmp_mask_in, u32 neg_mask_in,
+ s32 offset_in, const RoseInstruction *target_in)
+ : and_mask(std::move(and_mask_in)), cmp_mask(std::move(cmp_mask_in)),
+ neg_mask(neg_mask_in), offset(offset_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckMask32 &ri) const {
+ return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask &&
+ neg_mask == ri.neg_mask && offset == ri.offset &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, and_mask, cmp_mask, neg_mask, offset);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckMask32 &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask &&
+ neg_mask == ri.neg_mask && offset == ri.offset &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
class RoseInstrCheckMask64
: public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MASK_64,
ROSE_STRUCT_CHECK_MASK_64,
@@ -556,225 +556,225 @@ public:
}
};
-class RoseInstrCheckByte
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_BYTE,
- ROSE_STRUCT_CHECK_BYTE,
- RoseInstrCheckByte> {
-public:
- u8 and_mask;
- u8 cmp_mask;
- u8 negation;
- s32 offset;
- const RoseInstruction *target;
-
- RoseInstrCheckByte(u8 and_mask_in, u8 cmp_mask_in, u8 negation_in,
- s32 offset_in, const RoseInstruction *target_in)
- : and_mask(and_mask_in), cmp_mask(cmp_mask_in), negation(negation_in),
- offset(offset_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckByte &ri) const {
- return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask &&
- negation == ri.negation && offset == ri.offset &&
- target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, and_mask, cmp_mask, negation, offset);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckByte &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask &&
- negation == ri.negation && offset == ri.offset &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckShufti16x8
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_16x8,
- ROSE_STRUCT_CHECK_SHUFTI_16x8,
- RoseInstrCheckShufti16x8> {
-public:
- std::array<u8, 32> nib_mask;
- std::array<u8, 16> bucket_select_mask;
- u32 neg_mask;
- s32 offset;
- const RoseInstruction *target;
-
- RoseInstrCheckShufti16x8(std::array<u8, 32> nib_mask_in,
- std::array<u8, 16> bucket_select_mask_in,
- u32 neg_mask_in, s32 offset_in,
- const RoseInstruction *target_in)
- : nib_mask(std::move(nib_mask_in)),
- bucket_select_mask(std::move(bucket_select_mask_in)),
- neg_mask(neg_mask_in), offset(offset_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckShufti16x8 &ri) const {
- return nib_mask == ri.nib_mask &&
- bucket_select_mask == ri.bucket_select_mask &&
- neg_mask == ri.neg_mask && offset == ri.offset &&
- target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, nib_mask, bucket_select_mask, neg_mask, offset);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckShufti16x8 &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return nib_mask == ri.nib_mask &&
- bucket_select_mask == ri.bucket_select_mask &&
- neg_mask == ri.neg_mask && offset == ri.offset &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckShufti32x8
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_32x8,
- ROSE_STRUCT_CHECK_SHUFTI_32x8,
- RoseInstrCheckShufti32x8> {
-public:
- std::array<u8, 16> hi_mask;
- std::array<u8, 16> lo_mask;
- std::array<u8, 32> bucket_select_mask;
- u32 neg_mask;
- s32 offset;
- const RoseInstruction *target;
-
- RoseInstrCheckShufti32x8(std::array<u8, 16> hi_mask_in,
- std::array<u8, 16> lo_mask_in,
- std::array<u8, 32> bucket_select_mask_in,
- u32 neg_mask_in, s32 offset_in,
- const RoseInstruction *target_in)
- : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)),
- bucket_select_mask(std::move(bucket_select_mask_in)),
- neg_mask(neg_mask_in), offset(offset_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckShufti32x8 &ri) const {
- return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
- bucket_select_mask == ri.bucket_select_mask &&
- neg_mask == ri.neg_mask && offset == ri.offset &&
- target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask, neg_mask,
- offset);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckShufti32x8 &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
- bucket_select_mask == ri.bucket_select_mask &&
- neg_mask == ri.neg_mask && offset == ri.offset &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckShufti16x16
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_16x16,
- ROSE_STRUCT_CHECK_SHUFTI_16x16,
- RoseInstrCheckShufti16x16> {
-public:
- std::array<u8, 32> hi_mask;
- std::array<u8, 32> lo_mask;
- std::array<u8, 32> bucket_select_mask;
- u32 neg_mask;
- s32 offset;
- const RoseInstruction *target;
-
- RoseInstrCheckShufti16x16(std::array<u8, 32> hi_mask_in,
- std::array<u8, 32> lo_mask_in,
- std::array<u8, 32> bucket_select_mask_in,
- u32 neg_mask_in, s32 offset_in,
- const RoseInstruction *target_in)
- : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)),
- bucket_select_mask(std::move(bucket_select_mask_in)),
- neg_mask(neg_mask_in), offset(offset_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckShufti16x16 &ri) const {
- return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
- bucket_select_mask == ri.bucket_select_mask &&
- neg_mask == ri.neg_mask && offset == ri.offset &&
- target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask, neg_mask,
- offset);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckShufti16x16 &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
- bucket_select_mask == ri.bucket_select_mask &&
- neg_mask == ri.neg_mask && offset == ri.offset &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckShufti32x16
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_32x16,
- ROSE_STRUCT_CHECK_SHUFTI_32x16,
- RoseInstrCheckShufti32x16> {
-public:
- std::array<u8, 32> hi_mask;
- std::array<u8, 32> lo_mask;
- std::array<u8, 32> bucket_select_mask_hi;
- std::array<u8, 32> bucket_select_mask_lo;
- u32 neg_mask;
- s32 offset;
- const RoseInstruction *target;
-
- RoseInstrCheckShufti32x16(std::array<u8, 32> hi_mask_in,
- std::array<u8, 32> lo_mask_in,
- std::array<u8, 32> bucket_select_mask_hi_in,
- std::array<u8, 32> bucket_select_mask_lo_in,
- u32 neg_mask_in, s32 offset_in,
- const RoseInstruction *target_in)
- : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)),
- bucket_select_mask_hi(std::move(bucket_select_mask_hi_in)),
- bucket_select_mask_lo(std::move(bucket_select_mask_lo_in)),
- neg_mask(neg_mask_in), offset(offset_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckShufti32x16 &ri) const {
- return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
- bucket_select_mask_hi == ri.bucket_select_mask_hi &&
- bucket_select_mask_lo == ri.bucket_select_mask_lo &&
- neg_mask == ri.neg_mask && offset == ri.offset &&
- target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask_hi,
- bucket_select_mask_lo, neg_mask, offset);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckShufti32x16 &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
- bucket_select_mask_hi == ri.bucket_select_mask_hi &&
- bucket_select_mask_lo == ri.bucket_select_mask_lo &&
- neg_mask == ri.neg_mask && offset == ri.offset &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
+class RoseInstrCheckByte
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_BYTE,
+ ROSE_STRUCT_CHECK_BYTE,
+ RoseInstrCheckByte> {
+public:
+ u8 and_mask;
+ u8 cmp_mask;
+ u8 negation;
+ s32 offset;
+ const RoseInstruction *target;
+
+ RoseInstrCheckByte(u8 and_mask_in, u8 cmp_mask_in, u8 negation_in,
+ s32 offset_in, const RoseInstruction *target_in)
+ : and_mask(and_mask_in), cmp_mask(cmp_mask_in), negation(negation_in),
+ offset(offset_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckByte &ri) const {
+ return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask &&
+ negation == ri.negation && offset == ri.offset &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, and_mask, cmp_mask, negation, offset);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckByte &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask &&
+ negation == ri.negation && offset == ri.offset &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckShufti16x8
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_16x8,
+ ROSE_STRUCT_CHECK_SHUFTI_16x8,
+ RoseInstrCheckShufti16x8> {
+public:
+ std::array<u8, 32> nib_mask;
+ std::array<u8, 16> bucket_select_mask;
+ u32 neg_mask;
+ s32 offset;
+ const RoseInstruction *target;
+
+ RoseInstrCheckShufti16x8(std::array<u8, 32> nib_mask_in,
+ std::array<u8, 16> bucket_select_mask_in,
+ u32 neg_mask_in, s32 offset_in,
+ const RoseInstruction *target_in)
+ : nib_mask(std::move(nib_mask_in)),
+ bucket_select_mask(std::move(bucket_select_mask_in)),
+ neg_mask(neg_mask_in), offset(offset_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckShufti16x8 &ri) const {
+ return nib_mask == ri.nib_mask &&
+ bucket_select_mask == ri.bucket_select_mask &&
+ neg_mask == ri.neg_mask && offset == ri.offset &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, nib_mask, bucket_select_mask, neg_mask, offset);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckShufti16x8 &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return nib_mask == ri.nib_mask &&
+ bucket_select_mask == ri.bucket_select_mask &&
+ neg_mask == ri.neg_mask && offset == ri.offset &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckShufti32x8
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_32x8,
+ ROSE_STRUCT_CHECK_SHUFTI_32x8,
+ RoseInstrCheckShufti32x8> {
+public:
+ std::array<u8, 16> hi_mask;
+ std::array<u8, 16> lo_mask;
+ std::array<u8, 32> bucket_select_mask;
+ u32 neg_mask;
+ s32 offset;
+ const RoseInstruction *target;
+
+ RoseInstrCheckShufti32x8(std::array<u8, 16> hi_mask_in,
+ std::array<u8, 16> lo_mask_in,
+ std::array<u8, 32> bucket_select_mask_in,
+ u32 neg_mask_in, s32 offset_in,
+ const RoseInstruction *target_in)
+ : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)),
+ bucket_select_mask(std::move(bucket_select_mask_in)),
+ neg_mask(neg_mask_in), offset(offset_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckShufti32x8 &ri) const {
+ return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
+ bucket_select_mask == ri.bucket_select_mask &&
+ neg_mask == ri.neg_mask && offset == ri.offset &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask, neg_mask,
+ offset);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckShufti32x8 &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
+ bucket_select_mask == ri.bucket_select_mask &&
+ neg_mask == ri.neg_mask && offset == ri.offset &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckShufti16x16
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_16x16,
+ ROSE_STRUCT_CHECK_SHUFTI_16x16,
+ RoseInstrCheckShufti16x16> {
+public:
+ std::array<u8, 32> hi_mask;
+ std::array<u8, 32> lo_mask;
+ std::array<u8, 32> bucket_select_mask;
+ u32 neg_mask;
+ s32 offset;
+ const RoseInstruction *target;
+
+ RoseInstrCheckShufti16x16(std::array<u8, 32> hi_mask_in,
+ std::array<u8, 32> lo_mask_in,
+ std::array<u8, 32> bucket_select_mask_in,
+ u32 neg_mask_in, s32 offset_in,
+ const RoseInstruction *target_in)
+ : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)),
+ bucket_select_mask(std::move(bucket_select_mask_in)),
+ neg_mask(neg_mask_in), offset(offset_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckShufti16x16 &ri) const {
+ return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
+ bucket_select_mask == ri.bucket_select_mask &&
+ neg_mask == ri.neg_mask && offset == ri.offset &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask, neg_mask,
+ offset);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckShufti16x16 &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
+ bucket_select_mask == ri.bucket_select_mask &&
+ neg_mask == ri.neg_mask && offset == ri.offset &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckShufti32x16
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_32x16,
+ ROSE_STRUCT_CHECK_SHUFTI_32x16,
+ RoseInstrCheckShufti32x16> {
+public:
+ std::array<u8, 32> hi_mask;
+ std::array<u8, 32> lo_mask;
+ std::array<u8, 32> bucket_select_mask_hi;
+ std::array<u8, 32> bucket_select_mask_lo;
+ u32 neg_mask;
+ s32 offset;
+ const RoseInstruction *target;
+
+ RoseInstrCheckShufti32x16(std::array<u8, 32> hi_mask_in,
+ std::array<u8, 32> lo_mask_in,
+ std::array<u8, 32> bucket_select_mask_hi_in,
+ std::array<u8, 32> bucket_select_mask_lo_in,
+ u32 neg_mask_in, s32 offset_in,
+ const RoseInstruction *target_in)
+ : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)),
+ bucket_select_mask_hi(std::move(bucket_select_mask_hi_in)),
+ bucket_select_mask_lo(std::move(bucket_select_mask_lo_in)),
+ neg_mask(neg_mask_in), offset(offset_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckShufti32x16 &ri) const {
+ return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
+ bucket_select_mask_hi == ri.bucket_select_mask_hi &&
+ bucket_select_mask_lo == ri.bucket_select_mask_lo &&
+ neg_mask == ri.neg_mask && offset == ri.offset &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask_hi,
+ bucket_select_mask_lo, neg_mask, offset);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckShufti32x16 &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
+ bucket_select_mask_hi == ri.bucket_select_mask_hi &&
+ bucket_select_mask_lo == ri.bucket_select_mask_lo &&
+ neg_mask == ri.neg_mask && offset == ri.offset &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
class RoseInstrCheckShufti64x8
: public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_64x8,
ROSE_STRUCT_CHECK_SHUFTI_64x8,
@@ -878,1412 +878,1412 @@ public:
}
};
-class RoseInstrCheckInfix
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_INFIX,
- ROSE_STRUCT_CHECK_INFIX,
- RoseInstrCheckInfix> {
-public:
- u32 queue;
- u32 lag;
- ReportID report;
- const RoseInstruction *target;
-
- RoseInstrCheckInfix(u32 queue_in, u32 lag_in, ReportID report_in,
- const RoseInstruction *target_in)
- : queue(queue_in), lag(lag_in), report(report_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckInfix &ri) const {
- return queue == ri.queue && lag == ri.lag && report == ri.report &&
- target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, queue, lag, report);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckInfix &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return queue == ri.queue && lag == ri.lag && report == ri.report &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckPrefix
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_PREFIX,
- ROSE_STRUCT_CHECK_PREFIX,
- RoseInstrCheckPrefix> {
-public:
- u32 queue;
- u32 lag;
- ReportID report;
- const RoseInstruction *target;
-
- RoseInstrCheckPrefix(u32 queue_in, u32 lag_in, ReportID report_in,
- const RoseInstruction *target_in)
- : queue(queue_in), lag(lag_in), report(report_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckPrefix &ri) const {
- return queue == ri.queue && lag == ri.lag && report == ri.report &&
- target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, queue, lag, report);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckPrefix &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return queue == ri.queue && lag == ri.lag && report == ri.report &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrPushDelayed
- : public RoseInstrBaseNoTargets<ROSE_INSTR_PUSH_DELAYED,
- ROSE_STRUCT_PUSH_DELAYED,
- RoseInstrPushDelayed> {
-public:
- u8 delay;
- u32 index;
-
- RoseInstrPushDelayed(u8 delay_in, u32 index_in)
- : delay(delay_in), index(index_in) {}
-
- bool operator==(const RoseInstrPushDelayed &ri) const {
- return delay == ri.delay && index == ri.index;
- }
-
- size_t hash() const override {
- return hash_all(opcode, delay, index);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrPushDelayed &ri, const OffsetMap &,
- const OffsetMap &) const {
- return delay == ri.delay && index == ri.index;
- }
-};
-
-class RoseInstrCatchUp
- : public RoseInstrBaseTrivial<ROSE_INSTR_CATCH_UP, ROSE_STRUCT_CATCH_UP,
- RoseInstrCatchUp> {
-public:
- ~RoseInstrCatchUp() override;
-};
-
-class RoseInstrCatchUpMpv
- : public RoseInstrBaseTrivial<ROSE_INSTR_CATCH_UP_MPV,
- ROSE_STRUCT_CATCH_UP_MPV,
- RoseInstrCatchUpMpv> {
-public:
- ~RoseInstrCatchUpMpv() override;
-};
-
-class RoseInstrSomAdjust
- : public RoseInstrBaseNoTargets<ROSE_INSTR_SOM_ADJUST,
- ROSE_STRUCT_SOM_ADJUST,
- RoseInstrSomAdjust> {
-public:
- u32 distance;
-
- explicit RoseInstrSomAdjust(u32 distance_in) : distance(distance_in) {}
-
- bool operator==(const RoseInstrSomAdjust &ri) const {
- return distance == ri.distance;
- }
-
- size_t hash() const override {
- return hash_all(opcode, distance);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrSomAdjust &ri, const OffsetMap &,
- const OffsetMap &) const {
- return distance == ri.distance;
- }
-};
-
-class RoseInstrSomLeftfix
- : public RoseInstrBaseNoTargets<ROSE_INSTR_SOM_LEFTFIX,
- ROSE_STRUCT_SOM_LEFTFIX,
- RoseInstrSomLeftfix> {
-public:
- u32 queue;
- u32 lag;
-
- RoseInstrSomLeftfix(u32 queue_in, u32 lag_in)
- : queue(queue_in), lag(lag_in) {}
-
- bool operator==(const RoseInstrSomLeftfix &ri) const {
- return queue == ri.queue && lag == ri.lag;
- }
-
- size_t hash() const override {
- return hash_all(opcode, queue, lag);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrSomLeftfix &ri, const OffsetMap &,
- const OffsetMap &) const {
- return queue == ri.queue && lag == ri.lag;
- }
-};
-
-class RoseInstrSomFromReport
- : public RoseInstrBaseNoTargets<ROSE_INSTR_SOM_FROM_REPORT,
- ROSE_STRUCT_SOM_FROM_REPORT,
- RoseInstrSomFromReport> {
-public:
- som_operation som;
-
- RoseInstrSomFromReport() {
- std::memset(&som, 0, sizeof(som));
- }
-
- bool operator==(const RoseInstrSomFromReport &ri) const {
- return std::memcmp(&som, &ri.som, sizeof(som)) == 0;
- }
-
- size_t hash() const override {
- return hash_all(opcode, som.type, som.onmatch);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrSomFromReport &ri, const OffsetMap &,
- const OffsetMap &) const {
- return std::memcmp(&som, &ri.som, sizeof(som)) == 0;
- }
-};
-
-class RoseInstrSomZero
- : public RoseInstrBaseTrivial<ROSE_INSTR_SOM_ZERO, ROSE_STRUCT_SOM_ZERO,
- RoseInstrSomZero> {
-public:
- ~RoseInstrSomZero() override;
-};
-
-class RoseInstrTriggerInfix
- : public RoseInstrBaseNoTargets<ROSE_INSTR_TRIGGER_INFIX,
- ROSE_STRUCT_TRIGGER_INFIX,
- RoseInstrTriggerInfix> {
-public:
- u8 cancel;
- u32 queue;
- u32 event;
-
- RoseInstrTriggerInfix(u8 cancel_in, u32 queue_in, u32 event_in)
- : cancel(cancel_in), queue(queue_in), event(event_in) {}
-
- bool operator==(const RoseInstrTriggerInfix &ri) const {
- return cancel == ri.cancel && queue == ri.queue && event == ri.event;
- }
-
- size_t hash() const override {
- return hash_all(opcode, cancel, queue, event);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrTriggerInfix &ri, const OffsetMap &,
- const OffsetMap &) const {
- return cancel == ri.cancel && queue == ri.queue && event == ri.event;
- }
-};
-
-class RoseInstrTriggerSuffix
- : public RoseInstrBaseNoTargets<ROSE_INSTR_TRIGGER_SUFFIX,
- ROSE_STRUCT_TRIGGER_SUFFIX,
- RoseInstrTriggerSuffix> {
-public:
- u32 queue;
- u32 event;
-
- RoseInstrTriggerSuffix(u32 queue_in, u32 event_in)
- : queue(queue_in), event(event_in) {}
-
- bool operator==(const RoseInstrTriggerSuffix &ri) const {
- return queue == ri.queue && event == ri.event;
- }
-
- size_t hash() const override {
- return hash_all(opcode, queue, event);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrTriggerSuffix &ri, const OffsetMap &,
- const OffsetMap &) const {
- return queue == ri.queue && event == ri.event;
- }
-};
-
-class RoseInstrDedupe
- : public RoseInstrBaseOneTarget<ROSE_INSTR_DEDUPE, ROSE_STRUCT_DEDUPE,
- RoseInstrDedupe> {
-public:
- u8 quash_som;
- u32 dkey;
- s32 offset_adjust;
- const RoseInstruction *target;
-
- RoseInstrDedupe(u8 quash_som_in, u32 dkey_in, s32 offset_adjust_in,
- const RoseInstruction *target_in)
- : quash_som(quash_som_in), dkey(dkey_in),
- offset_adjust(offset_adjust_in), target(target_in) {}
-
- bool operator==(const RoseInstrDedupe &ri) const {
- return quash_som == ri.quash_som && dkey == ri.dkey &&
- offset_adjust == ri.offset_adjust && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, quash_som, dkey, offset_adjust);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrDedupe &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return quash_som == ri.quash_som && dkey == ri.dkey &&
- offset_adjust == ri.offset_adjust &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrDedupeSom
- : public RoseInstrBaseOneTarget<ROSE_INSTR_DEDUPE_SOM,
- ROSE_STRUCT_DEDUPE_SOM,
- RoseInstrDedupeSom> {
-public:
- u8 quash_som;
- u32 dkey;
- s32 offset_adjust;
- const RoseInstruction *target;
-
- RoseInstrDedupeSom(u8 quash_som_in, u32 dkey_in, s32 offset_adjust_in,
- const RoseInstruction *target_in)
- : quash_som(quash_som_in), dkey(dkey_in),
- offset_adjust(offset_adjust_in), target(target_in) {}
-
- bool operator==(const RoseInstrDedupeSom &ri) const {
- return quash_som == ri.quash_som && dkey == ri.dkey &&
- offset_adjust == ri.offset_adjust && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, quash_som, dkey, offset_adjust);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrDedupeSom &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return quash_som == ri.quash_som && dkey == ri.dkey &&
- offset_adjust == ri.offset_adjust &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrReportChain
- : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_CHAIN,
- ROSE_STRUCT_REPORT_CHAIN,
- RoseInstrReportChain> {
-public:
- u32 event;
- u64a top_squash_distance;
-
- RoseInstrReportChain(u32 event_in, u32 top_squash_distance_in)
- : event(event_in), top_squash_distance(top_squash_distance_in) {}
-
- bool operator==(const RoseInstrReportChain &ri) const {
- return event == ri.event &&
- top_squash_distance == ri.top_squash_distance;
- }
-
- size_t hash() const override {
- return hash_all(opcode, event, top_squash_distance);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrReportChain &ri, const OffsetMap &,
- const OffsetMap &) const {
- return event == ri.event &&
- top_squash_distance == ri.top_squash_distance;
- }
-};
-
-class RoseInstrReportSomInt
- : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_SOM_INT,
- ROSE_STRUCT_REPORT_SOM_INT,
- RoseInstrReportSomInt> {
-public:
- som_operation som;
-
- RoseInstrReportSomInt() {
- std::memset(&som, 0, sizeof(som));
- }
-
- bool operator==(const RoseInstrReportSomInt &ri) const {
- return std::memcmp(&som, &ri.som, sizeof(som)) == 0;
- }
-
- size_t hash() const override {
- return hash_all(opcode, som.type, som.onmatch);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrReportSomInt &ri, const OffsetMap &,
- const OffsetMap &) const {
- return std::memcmp(&som, &ri.som, sizeof(som)) == 0;
- }
-};
-
-class RoseInstrReportSomAware
- : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_SOM_AWARE,
- ROSE_STRUCT_REPORT_SOM_AWARE,
- RoseInstrReportSomAware> {
-public:
- som_operation som;
-
- RoseInstrReportSomAware() {
- std::memset(&som, 0, sizeof(som));
- }
-
- bool operator==(const RoseInstrReportSomAware &ri) const {
- return std::memcmp(&som, &ri.som, sizeof(som)) == 0;
- }
-
- size_t hash() const override {
- return hash_all(opcode, som.type, som.onmatch);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrReportSomAware &ri, const OffsetMap &,
- const OffsetMap &) const {
- return std::memcmp(&som, &ri.som, sizeof(som)) == 0;
- }
-};
-
-class RoseInstrReport
- : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT, ROSE_STRUCT_REPORT,
- RoseInstrReport> {
-public:
- ReportID onmatch;
- s32 offset_adjust;
-
- RoseInstrReport(ReportID onmatch_in, s32 offset_adjust_in)
- : onmatch(onmatch_in), offset_adjust(offset_adjust_in) {}
-
- bool operator==(const RoseInstrReport &ri) const {
- return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust;
- }
-
- size_t hash() const override {
- return hash_all(opcode, onmatch, offset_adjust);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrReport &ri, const OffsetMap &,
- const OffsetMap &) const {
- return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust;
- }
-};
-
-class RoseInstrReportExhaust
- : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_EXHAUST,
- ROSE_STRUCT_REPORT_EXHAUST,
- RoseInstrReportExhaust> {
-public:
- ReportID onmatch;
- s32 offset_adjust;
- u32 ekey;
-
- RoseInstrReportExhaust(ReportID onmatch_in, s32 offset_adjust_in,
- u32 ekey_in)
- : onmatch(onmatch_in), offset_adjust(offset_adjust_in), ekey(ekey_in) {}
-
- bool operator==(const RoseInstrReportExhaust &ri) const {
- return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust &&
- ekey == ri.ekey;
- }
-
- size_t hash() const override {
- return hash_all(opcode, onmatch, offset_adjust, ekey);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrReportExhaust &ri, const OffsetMap &,
- const OffsetMap &) const {
- return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust &&
- ekey == ri.ekey;
- }
-};
-
-class RoseInstrReportSom
- : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_SOM,
- ROSE_STRUCT_REPORT_SOM,
- RoseInstrReportSom> {
-public:
- ReportID onmatch;
- s32 offset_adjust;
-
- RoseInstrReportSom(ReportID onmatch_in, s32 offset_adjust_in)
- : onmatch(onmatch_in), offset_adjust(offset_adjust_in) {}
-
- bool operator==(const RoseInstrReportSom &ri) const {
- return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust;
- }
-
- size_t hash() const override {
- return hash_all(opcode, onmatch, offset_adjust);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrReportSom &ri, const OffsetMap &,
- const OffsetMap &) const {
- return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust;
- }
-};
-
-class RoseInstrReportSomExhaust
- : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_SOM_EXHAUST,
- ROSE_STRUCT_REPORT_SOM_EXHAUST,
- RoseInstrReportSomExhaust> {
-public:
- ReportID onmatch;
- s32 offset_adjust;
- u32 ekey;
-
- RoseInstrReportSomExhaust(ReportID onmatch_in, s32 offset_adjust_in,
- u32 ekey_in)
- : onmatch(onmatch_in), offset_adjust(offset_adjust_in), ekey(ekey_in) {}
-
- bool operator==(const RoseInstrReportSomExhaust &ri) const {
- return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust &&
- ekey == ri.ekey;
- }
-
- size_t hash() const override {
- return hash_all(opcode, onmatch, offset_adjust, ekey);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrReportSomExhaust &ri, const OffsetMap &,
- const OffsetMap &) const {
- return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust &&
- ekey == ri.ekey;
- }
-};
-
-class RoseInstrDedupeAndReport
- : public RoseInstrBaseOneTarget<ROSE_INSTR_DEDUPE_AND_REPORT,
- ROSE_STRUCT_DEDUPE_AND_REPORT,
- RoseInstrDedupeAndReport> {
-public:
- u8 quash_som;
- u32 dkey;
- ReportID onmatch;
- s32 offset_adjust;
- const RoseInstruction *target;
-
- RoseInstrDedupeAndReport(u8 quash_som_in, u32 dkey_in, ReportID onmatch_in,
- s32 offset_adjust_in,
- const RoseInstruction *target_in)
- : quash_som(quash_som_in), dkey(dkey_in), onmatch(onmatch_in),
- offset_adjust(offset_adjust_in), target(target_in) {}
-
- bool operator==(const RoseInstrDedupeAndReport &ri) const {
- return quash_som == ri.quash_som && dkey == ri.dkey &&
- onmatch == ri.onmatch && offset_adjust == ri.offset_adjust &&
- target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, quash_som, dkey, onmatch, offset_adjust);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrDedupeAndReport &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return quash_som == ri.quash_som && dkey == ri.dkey &&
- onmatch == ri.onmatch && offset_adjust == ri.offset_adjust &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrFinalReport
- : public RoseInstrBaseNoTargets<ROSE_INSTR_FINAL_REPORT,
- ROSE_STRUCT_FINAL_REPORT,
- RoseInstrFinalReport> {
-public:
- ReportID onmatch;
- s32 offset_adjust;
-
- RoseInstrFinalReport(ReportID onmatch_in, s32 offset_adjust_in)
- : onmatch(onmatch_in), offset_adjust(offset_adjust_in) {}
-
- bool operator==(const RoseInstrFinalReport &ri) const {
- return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust;
- }
-
- size_t hash() const override {
- return hash_all(opcode, onmatch, offset_adjust);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrFinalReport &ri, const OffsetMap &,
- const OffsetMap &) const {
- return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust;
- }
-};
-
-class RoseInstrCheckExhausted
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_EXHAUSTED,
- ROSE_STRUCT_CHECK_EXHAUSTED,
- RoseInstrCheckExhausted> {
-public:
- u32 ekey;
- const RoseInstruction *target;
-
- RoseInstrCheckExhausted(u32 ekey_in, const RoseInstruction *target_in)
- : ekey(ekey_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckExhausted &ri) const {
- return ekey == ri.ekey && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, ekey);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckExhausted &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return ekey == ri.ekey &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckMinLength
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MIN_LENGTH,
- ROSE_STRUCT_CHECK_MIN_LENGTH,
- RoseInstrCheckMinLength> {
-public:
- s32 end_adj;
- u64a min_length;
- const RoseInstruction *target;
-
- RoseInstrCheckMinLength(s32 end_adj_in, u64a min_length_in,
- const RoseInstruction *target_in)
- : end_adj(end_adj_in), min_length(min_length_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckMinLength &ri) const {
- return end_adj == ri.end_adj && min_length == ri.min_length &&
- target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, end_adj, min_length);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckMinLength &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return end_adj == ri.end_adj && min_length == ri.min_length &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrSetState
- : public RoseInstrBaseNoTargets<ROSE_INSTR_SET_STATE, ROSE_STRUCT_SET_STATE,
- RoseInstrSetState> {
-public:
- u32 index;
-
- explicit RoseInstrSetState(u32 index_in) : index(index_in) {}
-
- bool operator==(const RoseInstrSetState &ri) const {
- return index == ri.index;
- }
-
- size_t hash() const override {
- return hash_all(opcode, index);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrSetState &ri, const OffsetMap &,
- const OffsetMap &) const {
- return index == ri.index;
- }
-};
-
-class RoseInstrSetGroups
- : public RoseInstrBaseNoTargets<ROSE_INSTR_SET_GROUPS,
- ROSE_STRUCT_SET_GROUPS,
- RoseInstrSetGroups> {
-public:
- rose_group groups;
-
- explicit RoseInstrSetGroups(rose_group groups_in) : groups(groups_in) {}
-
- bool operator==(const RoseInstrSetGroups &ri) const {
- return groups == ri.groups;
- }
-
- size_t hash() const override {
- return hash_all(opcode, groups);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrSetGroups &ri, const OffsetMap &,
- const OffsetMap &) const {
- return groups == ri.groups;
- }
-};
-
-class RoseInstrSquashGroups
- : public RoseInstrBaseNoTargets<ROSE_INSTR_SQUASH_GROUPS,
- ROSE_STRUCT_SQUASH_GROUPS,
- RoseInstrSquashGroups> {
-public:
- rose_group groups;
-
- explicit RoseInstrSquashGroups(rose_group groups_in) : groups(groups_in) {}
-
- bool operator==(const RoseInstrSquashGroups &ri) const {
- return groups == ri.groups;
- }
-
- size_t hash() const override {
- return hash_all(opcode, groups);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrSquashGroups &ri, const OffsetMap &,
- const OffsetMap &) const {
- return groups == ri.groups;
- }
-};
-
-class RoseInstrCheckState
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_STATE,
- ROSE_STRUCT_CHECK_STATE,
- RoseInstrCheckState> {
-public:
- u32 index;
- const RoseInstruction *target;
-
- RoseInstrCheckState(u32 index_in, const RoseInstruction *target_in)
- : index(index_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckState &ri) const {
- return index == ri.index && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, index);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckState &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return index == ri.index &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrSparseIterBegin
- : public RoseInstrBase<ROSE_INSTR_SPARSE_ITER_BEGIN,
- ROSE_STRUCT_SPARSE_ITER_BEGIN,
- RoseInstrSparseIterBegin> {
-public:
- u32 num_keys; // total number of multibit keys
- std::vector<std::pair<u32, const RoseInstruction *>> jump_table;
- const RoseInstruction *target;
-
- RoseInstrSparseIterBegin(u32 num_keys_in,
- const RoseInstruction *target_in)
- : num_keys(num_keys_in), target(target_in) {}
-
- bool operator==(const RoseInstrSparseIterBegin &ri) const {
- return num_keys == ri.num_keys && jump_table == ri.jump_table &&
- target == ri.target;
- }
-
- size_t hash() const override {
- size_t v = hash_all(opcode, num_keys);
- for (const u32 &key : jump_table | boost::adaptors::map_keys) {
- hash_combine(v, key);
- }
- return v;
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- void update_target(const RoseInstruction *old_target,
- const RoseInstruction *new_target) override {
- if (target == old_target) {
- target = new_target;
- }
- for (auto &jump : jump_table) {
- if (jump.second == old_target) {
- jump.second = new_target;
- }
- }
- }
-
- bool equiv_to(const RoseInstrSparseIterBegin &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- if (iter_offset != ri.iter_offset ||
- offsets.at(target) != other_offsets.at(ri.target)) {
- return false;
- }
- if (jump_table.size() != ri.jump_table.size()) {
- return false;
- }
- auto it1 = jump_table.begin(), it2 = ri.jump_table.begin();
- for (; it1 != jump_table.end(); ++it1, ++it2) {
- if (it1->first != it2->first) {
- return false;
- }
- if (offsets.at(it1->second) != other_offsets.at(it2->second)) {
- return false;
- }
- }
- return true;
- }
-
-private:
- friend class RoseInstrSparseIterNext;
-
- // These variables allow us to use the same multibit iterator and jump
- // table in subsequent SPARSE_ITER_NEXT write() operations.
- mutable bool is_written = false;
- mutable u32 iter_offset = 0;
- mutable u32 jump_table_offset = 0;
-};
-
-class RoseInstrSparseIterNext
- : public RoseInstrBase<ROSE_INSTR_SPARSE_ITER_NEXT,
- ROSE_STRUCT_SPARSE_ITER_NEXT,
- RoseInstrSparseIterNext> {
-public:
- u32 state;
- const RoseInstrSparseIterBegin *begin;
- const RoseInstruction *target;
-
- RoseInstrSparseIterNext(u32 state_in,
- const RoseInstrSparseIterBegin *begin_in,
- const RoseInstruction *target_in)
- : state(state_in), begin(begin_in), target(target_in) {}
-
- bool operator==(const RoseInstrSparseIterNext &ri) const {
- return state == ri.state && begin == ri.begin && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, state);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- void update_target(const RoseInstruction *old_target,
- const RoseInstruction *new_target) override {
- if (target == old_target) {
- target = new_target;
- }
- if (begin == old_target) {
- assert(new_target->code() == ROSE_INSTR_SPARSE_ITER_BEGIN);
- begin = static_cast<const RoseInstrSparseIterBegin *>(new_target);
- }
- }
-
- bool equiv_to(const RoseInstrSparseIterNext &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return state == ri.state &&
- offsets.at(begin) == other_offsets.at(ri.begin) &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrSparseIterAny
- : public RoseInstrBaseOneTarget<ROSE_INSTR_SPARSE_ITER_ANY,
- ROSE_STRUCT_SPARSE_ITER_ANY,
- RoseInstrSparseIterAny> {
-public:
- u32 num_keys; // total number of multibit keys
- std::vector<u32> keys;
- const RoseInstruction *target;
-
- RoseInstrSparseIterAny(u32 num_keys_in, std::vector<u32> keys_in,
- const RoseInstruction *target_in)
- : num_keys(num_keys_in), keys(std::move(keys_in)), target(target_in) {}
-
- bool operator==(const RoseInstrSparseIterAny &ri) const {
- return num_keys == ri.num_keys && keys == ri.keys &&
- target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, num_keys, keys);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrSparseIterAny &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return num_keys == ri.num_keys && keys == ri.keys &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrEnginesEod
- : public RoseInstrBaseNoTargets<ROSE_INSTR_ENGINES_EOD,
- ROSE_STRUCT_ENGINES_EOD,
- RoseInstrEnginesEod> {
-public:
- u32 iter_offset;
-
- explicit RoseInstrEnginesEod(u32 iter_in) : iter_offset(iter_in) {}
-
- bool operator==(const RoseInstrEnginesEod &ri) const {
- return iter_offset == ri.iter_offset;
- }
-
- size_t hash() const override {
- return hash_all(opcode, iter_offset);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrEnginesEod &ri, const OffsetMap &,
- const OffsetMap &) const {
- return iter_offset == ri.iter_offset;
- }
-};
-
-class RoseInstrSuffixesEod
- : public RoseInstrBaseTrivial<ROSE_INSTR_SUFFIXES_EOD,
- ROSE_STRUCT_SUFFIXES_EOD,
- RoseInstrSuffixesEod> {
-public:
- ~RoseInstrSuffixesEod() override;
-};
-
-class RoseInstrMatcherEod : public RoseInstrBaseTrivial<ROSE_INSTR_MATCHER_EOD,
- ROSE_STRUCT_MATCHER_EOD,
- RoseInstrMatcherEod> {
-public:
- ~RoseInstrMatcherEod() override;
-};
-
-class RoseInstrCheckLongLit
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_LONG_LIT,
- ROSE_STRUCT_CHECK_LONG_LIT,
- RoseInstrCheckLongLit> {
-public:
- std::string literal;
- const RoseInstruction *target;
-
- RoseInstrCheckLongLit(std::string literal_in,
- const RoseInstruction *target_in)
- : literal(std::move(literal_in)), target(target_in) {}
-
- bool operator==(const RoseInstrCheckLongLit &ri) const {
- return literal == ri.literal && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, literal);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckLongLit &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return literal == ri.literal &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckLongLitNocase
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_LONG_LIT_NOCASE,
- ROSE_STRUCT_CHECK_LONG_LIT_NOCASE,
- RoseInstrCheckLongLitNocase> {
-public:
- std::string literal;
- const RoseInstruction *target;
-
- RoseInstrCheckLongLitNocase(std::string literal_in,
- const RoseInstruction *target_in)
- : literal(std::move(literal_in)), target(target_in) {
- upperString(literal);
- }
-
- bool operator==(const RoseInstrCheckLongLitNocase &ri) const {
- return literal == ri.literal && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, literal);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckLongLitNocase &ri,
- const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return literal == ri.literal &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckMedLit
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MED_LIT,
- ROSE_STRUCT_CHECK_MED_LIT,
- RoseInstrCheckMedLit> {
-public:
- std::string literal;
- const RoseInstruction *target;
-
- explicit RoseInstrCheckMedLit(std::string literal_in,
- const RoseInstruction *target_in)
- : literal(std::move(literal_in)), target(target_in) {}
-
- bool operator==(const RoseInstrCheckMedLit &ri) const {
- return literal == ri.literal && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, literal);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckMedLit &ri, const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return literal == ri.literal &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckMedLitNocase
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MED_LIT_NOCASE,
- ROSE_STRUCT_CHECK_MED_LIT_NOCASE,
- RoseInstrCheckMedLitNocase> {
-public:
- std::string literal;
- const RoseInstruction *target;
-
- explicit RoseInstrCheckMedLitNocase(std::string literal_in,
- const RoseInstruction *target_in)
- : literal(std::move(literal_in)), target(target_in) {
- upperString(literal);
- }
-
- bool operator==(const RoseInstrCheckMedLitNocase &ri) const {
- return literal == ri.literal && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, literal);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckMedLitNocase &ri,
- const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return literal == ri.literal &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrClearWorkDone
- : public RoseInstrBaseTrivial<ROSE_INSTR_CLEAR_WORK_DONE,
- ROSE_STRUCT_CLEAR_WORK_DONE,
- RoseInstrClearWorkDone> {
-public:
- ~RoseInstrClearWorkDone() override;
-};
-
-class RoseInstrMultipathLookaround
- : public RoseInstrBaseOneTarget<ROSE_INSTR_MULTIPATH_LOOKAROUND,
- ROSE_STRUCT_MULTIPATH_LOOKAROUND,
- RoseInstrMultipathLookaround> {
-public:
- std::vector<std::vector<LookEntry>> multi_look;
- s32 last_start;
- std::array<u8, 16> start_mask;
- const RoseInstruction *target;
-
- RoseInstrMultipathLookaround(std::vector<std::vector<LookEntry>> ml,
- s32 last_start_in,
- std::array<u8, 16> start_mask_in,
- const RoseInstruction *target_in)
- : multi_look(std::move(ml)), last_start(last_start_in),
- start_mask(std::move(start_mask_in)), target(target_in) {}
-
- bool operator==(const RoseInstrMultipathLookaround &ri) const {
- return multi_look == ri.multi_look && last_start == ri.last_start
- && start_mask == ri.start_mask && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, multi_look, last_start, start_mask);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrMultipathLookaround &ri,
- const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return multi_look == ri.multi_look && last_start == ri.last_start
- && start_mask == ri.start_mask
- && offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckMultipathShufti16x8
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MULTIPATH_SHUFTI_16x8,
- ROSE_STRUCT_CHECK_MULTIPATH_SHUFTI_16x8,
- RoseInstrCheckMultipathShufti16x8> {
-public:
- std::array<u8, 32> nib_mask;
- std::array<u8, 64> bucket_select_mask;
- std::array<u8, 64> data_select_mask;
- u16 hi_bits_mask;
- u16 lo_bits_mask;
- u16 neg_mask;
- s32 base_offset;
- s32 last_start;
- const RoseInstruction *target;
-
- RoseInstrCheckMultipathShufti16x8(std::array<u8, 32> nib_mask_in,
- std::array<u8, 64> bucket_select_mask_in,
- std::array<u8, 64> data_select_mask_in,
- u16 hi_bits_mask_in, u16 lo_bits_mask_in,
- u16 neg_mask_in, s32 base_offset_in,
- s32 last_start_in,
- const RoseInstruction *target_in)
- : nib_mask(std::move(nib_mask_in)),
- bucket_select_mask(std::move(bucket_select_mask_in)),
- data_select_mask(std::move(data_select_mask_in)),
- hi_bits_mask(hi_bits_mask_in), lo_bits_mask(lo_bits_mask_in),
- neg_mask(neg_mask_in), base_offset(base_offset_in),
- last_start(last_start_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckMultipathShufti16x8 &ri) const {
- return nib_mask == ri.nib_mask &&
- bucket_select_mask == ri.bucket_select_mask &&
- data_select_mask == ri.data_select_mask &&
- hi_bits_mask == ri.hi_bits_mask &&
- lo_bits_mask == ri.lo_bits_mask &&
- neg_mask == ri.neg_mask && base_offset == ri.base_offset &&
- last_start == ri.last_start && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, nib_mask, bucket_select_mask, data_select_mask,
- hi_bits_mask, lo_bits_mask, neg_mask, base_offset,
- last_start);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckMultipathShufti16x8 &ri,
- const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return nib_mask == ri.nib_mask &&
- bucket_select_mask == ri.bucket_select_mask &&
- data_select_mask == ri.data_select_mask &&
- hi_bits_mask == ri.hi_bits_mask &&
- lo_bits_mask == ri.lo_bits_mask && neg_mask == ri.neg_mask &&
- base_offset == ri.base_offset && last_start == ri.last_start &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckMultipathShufti32x8
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MULTIPATH_SHUFTI_32x8,
- ROSE_STRUCT_CHECK_MULTIPATH_SHUFTI_32x8,
- RoseInstrCheckMultipathShufti32x8> {
-public:
- std::array<u8, 32> hi_mask;
- std::array<u8, 32> lo_mask;
- std::array<u8, 64> bucket_select_mask;
- std::array<u8, 64> data_select_mask;
- u32 hi_bits_mask;
- u32 lo_bits_mask;
- u32 neg_mask;
- s32 base_offset;
- s32 last_start;
- const RoseInstruction *target;
-
- RoseInstrCheckMultipathShufti32x8(std::array<u8, 32> hi_mask_in,
- std::array<u8, 32> lo_mask_in,
- std::array<u8, 64> bucket_select_mask_in,
- std::array<u8, 64> data_select_mask_in,
- u32 hi_bits_mask_in, u32 lo_bits_mask_in,
- u32 neg_mask_in, s32 base_offset_in,
- s32 last_start_in,
- const RoseInstruction *target_in)
- : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)),
- bucket_select_mask(std::move(bucket_select_mask_in)),
- data_select_mask(std::move(data_select_mask_in)),
- hi_bits_mask(hi_bits_mask_in), lo_bits_mask(lo_bits_mask_in),
- neg_mask(neg_mask_in), base_offset(base_offset_in),
- last_start(last_start_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckMultipathShufti32x8 &ri) const {
- return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
- bucket_select_mask == ri.bucket_select_mask &&
- data_select_mask == ri.data_select_mask &&
- hi_bits_mask == ri.hi_bits_mask &&
- lo_bits_mask == ri.lo_bits_mask &&
- neg_mask == ri.neg_mask && base_offset == ri.base_offset &&
- last_start == ri.last_start && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask,
- data_select_mask, hi_bits_mask, lo_bits_mask, neg_mask,
- base_offset, last_start);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckMultipathShufti32x8 &ri,
- const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
- bucket_select_mask == ri.bucket_select_mask &&
- data_select_mask == ri.data_select_mask &&
- hi_bits_mask == ri.hi_bits_mask &&
- lo_bits_mask == ri.lo_bits_mask && neg_mask == ri.neg_mask &&
- base_offset == ri.base_offset && last_start == ri.last_start &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckMultipathShufti32x16
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MULTIPATH_SHUFTI_32x16,
- ROSE_STRUCT_CHECK_MULTIPATH_SHUFTI_32x16,
- RoseInstrCheckMultipathShufti32x16> {
-public:
- std::array<u8, 32> hi_mask;
- std::array<u8, 32> lo_mask;
- std::array<u8, 64> bucket_select_mask_hi;
- std::array<u8, 64> bucket_select_mask_lo;
- std::array<u8, 64> data_select_mask;
- u32 hi_bits_mask;
- u32 lo_bits_mask;
- u32 neg_mask;
- s32 base_offset;
- s32 last_start;
- const RoseInstruction *target;
-
- RoseInstrCheckMultipathShufti32x16(std::array<u8, 32> hi_mask_in,
- std::array<u8, 32> lo_mask_in,
- std::array<u8, 64> bucket_select_mask_hi_in,
- std::array<u8, 64> bucket_select_mask_lo_in,
- std::array<u8, 64> data_select_mask_in,
- u32 hi_bits_mask_in, u32 lo_bits_mask_in,
- u32 neg_mask_in, s32 base_offset_in,
- s32 last_start_in,
- const RoseInstruction *target_in)
- : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)),
- bucket_select_mask_hi(std::move(bucket_select_mask_hi_in)),
- bucket_select_mask_lo(std::move(bucket_select_mask_lo_in)),
- data_select_mask(std::move(data_select_mask_in)),
- hi_bits_mask(hi_bits_mask_in), lo_bits_mask(lo_bits_mask_in),
- neg_mask(neg_mask_in), base_offset(base_offset_in),
- last_start(last_start_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckMultipathShufti32x16 &ri) const {
- return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
- bucket_select_mask_hi == ri.bucket_select_mask_hi &&
- bucket_select_mask_lo == ri.bucket_select_mask_lo &&
- data_select_mask == ri.data_select_mask &&
- hi_bits_mask == ri.hi_bits_mask &&
- lo_bits_mask == ri.lo_bits_mask &&
- neg_mask == ri.neg_mask && base_offset == ri.base_offset &&
- last_start == ri.last_start && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask_hi,
- bucket_select_mask_lo, data_select_mask, hi_bits_mask,
- lo_bits_mask, neg_mask, base_offset, last_start);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckMultipathShufti32x16 &ri,
- const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
- bucket_select_mask_hi == ri.bucket_select_mask_hi &&
- bucket_select_mask_lo == ri.bucket_select_mask_lo &&
- data_select_mask == ri.data_select_mask &&
- hi_bits_mask == ri.hi_bits_mask &&
- lo_bits_mask == ri.lo_bits_mask && neg_mask == ri.neg_mask &&
- base_offset == ri.base_offset && last_start == ri.last_start &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrCheckMultipathShufti64
- : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MULTIPATH_SHUFTI_64,
- ROSE_STRUCT_CHECK_MULTIPATH_SHUFTI_64,
- RoseInstrCheckMultipathShufti64> {
-public:
- std::array<u8, 32> hi_mask;
- std::array<u8, 32> lo_mask;
- std::array<u8, 64> bucket_select_mask;
- std::array<u8, 64> data_select_mask;
- u64a hi_bits_mask;
- u64a lo_bits_mask;
- u64a neg_mask;
- s32 base_offset;
- s32 last_start;
- const RoseInstruction *target;
-
- RoseInstrCheckMultipathShufti64(std::array<u8, 32> hi_mask_in,
- std::array<u8, 32> lo_mask_in,
- std::array<u8, 64> bucket_select_mask_in,
- std::array<u8, 64> data_select_mask_in,
- u64a hi_bits_mask_in, u64a lo_bits_mask_in,
- u64a neg_mask_in, s32 base_offset_in,
- s32 last_start_in,
- const RoseInstruction *target_in)
- : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)),
- bucket_select_mask(std::move(bucket_select_mask_in)),
- data_select_mask(std::move(data_select_mask_in)),
- hi_bits_mask(hi_bits_mask_in), lo_bits_mask(lo_bits_mask_in),
- neg_mask(neg_mask_in), base_offset(base_offset_in),
- last_start(last_start_in), target(target_in) {}
-
- bool operator==(const RoseInstrCheckMultipathShufti64 &ri) const {
- return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
- bucket_select_mask == ri.bucket_select_mask &&
- data_select_mask == ri.data_select_mask &&
- hi_bits_mask == ri.hi_bits_mask &&
- lo_bits_mask == ri.lo_bits_mask &&
- neg_mask == ri.neg_mask && base_offset == ri.base_offset &&
- last_start == ri.last_start && target == ri.target;
- }
-
- size_t hash() const override {
- return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask,
- data_select_mask, hi_bits_mask, lo_bits_mask, neg_mask,
- base_offset, last_start);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrCheckMultipathShufti64 &ri,
- const OffsetMap &offsets,
- const OffsetMap &other_offsets) const {
- return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
- bucket_select_mask == ri.bucket_select_mask &&
- data_select_mask == ri.data_select_mask &&
- hi_bits_mask == ri.hi_bits_mask &&
- lo_bits_mask == ri.lo_bits_mask && neg_mask == ri.neg_mask &&
- base_offset == ri.base_offset && last_start == ri.last_start &&
- offsets.at(target) == other_offsets.at(ri.target);
- }
-};
-
-class RoseInstrIncludedJump
- : public RoseInstrBaseNoTargets<ROSE_INSTR_INCLUDED_JUMP,
- ROSE_STRUCT_INCLUDED_JUMP,
- RoseInstrIncludedJump> {
-public:
- u32 child_offset;
- u8 squash;
-
- RoseInstrIncludedJump(u32 child_offset_in, u8 squash_in)
- : child_offset(child_offset_in), squash(squash_in) {}
-
- bool operator==(const RoseInstrIncludedJump &ri) const {
- return child_offset == ri.child_offset && squash == ri.squash;
- }
-
- size_t hash() const override {
- return hash_all(static_cast<int>(opcode), child_offset, squash);
- }
-
- void write(void *dest, RoseEngineBlob &blob,
- const OffsetMap &offset_map) const override;
-
- bool equiv_to(const RoseInstrIncludedJump &ri, const OffsetMap &,
- const OffsetMap &) const {
- return child_offset == ri.child_offset && squash == ri.squash;
- }
-};
-
+class RoseInstrCheckInfix
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_INFIX,
+ ROSE_STRUCT_CHECK_INFIX,
+ RoseInstrCheckInfix> {
+public:
+ u32 queue;
+ u32 lag;
+ ReportID report;
+ const RoseInstruction *target;
+
+ RoseInstrCheckInfix(u32 queue_in, u32 lag_in, ReportID report_in,
+ const RoseInstruction *target_in)
+ : queue(queue_in), lag(lag_in), report(report_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckInfix &ri) const {
+ return queue == ri.queue && lag == ri.lag && report == ri.report &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, queue, lag, report);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckInfix &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return queue == ri.queue && lag == ri.lag && report == ri.report &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckPrefix
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_PREFIX,
+ ROSE_STRUCT_CHECK_PREFIX,
+ RoseInstrCheckPrefix> {
+public:
+ u32 queue;
+ u32 lag;
+ ReportID report;
+ const RoseInstruction *target;
+
+ RoseInstrCheckPrefix(u32 queue_in, u32 lag_in, ReportID report_in,
+ const RoseInstruction *target_in)
+ : queue(queue_in), lag(lag_in), report(report_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckPrefix &ri) const {
+ return queue == ri.queue && lag == ri.lag && report == ri.report &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, queue, lag, report);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckPrefix &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return queue == ri.queue && lag == ri.lag && report == ri.report &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrPushDelayed
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_PUSH_DELAYED,
+ ROSE_STRUCT_PUSH_DELAYED,
+ RoseInstrPushDelayed> {
+public:
+ u8 delay;
+ u32 index;
+
+ RoseInstrPushDelayed(u8 delay_in, u32 index_in)
+ : delay(delay_in), index(index_in) {}
+
+ bool operator==(const RoseInstrPushDelayed &ri) const {
+ return delay == ri.delay && index == ri.index;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, delay, index);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrPushDelayed &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return delay == ri.delay && index == ri.index;
+ }
+};
+
+class RoseInstrCatchUp
+ : public RoseInstrBaseTrivial<ROSE_INSTR_CATCH_UP, ROSE_STRUCT_CATCH_UP,
+ RoseInstrCatchUp> {
+public:
+ ~RoseInstrCatchUp() override;
+};
+
+class RoseInstrCatchUpMpv
+ : public RoseInstrBaseTrivial<ROSE_INSTR_CATCH_UP_MPV,
+ ROSE_STRUCT_CATCH_UP_MPV,
+ RoseInstrCatchUpMpv> {
+public:
+ ~RoseInstrCatchUpMpv() override;
+};
+
+class RoseInstrSomAdjust
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_SOM_ADJUST,
+ ROSE_STRUCT_SOM_ADJUST,
+ RoseInstrSomAdjust> {
+public:
+ u32 distance;
+
+ explicit RoseInstrSomAdjust(u32 distance_in) : distance(distance_in) {}
+
+ bool operator==(const RoseInstrSomAdjust &ri) const {
+ return distance == ri.distance;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, distance);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrSomAdjust &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return distance == ri.distance;
+ }
+};
+
+class RoseInstrSomLeftfix
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_SOM_LEFTFIX,
+ ROSE_STRUCT_SOM_LEFTFIX,
+ RoseInstrSomLeftfix> {
+public:
+ u32 queue;
+ u32 lag;
+
+ RoseInstrSomLeftfix(u32 queue_in, u32 lag_in)
+ : queue(queue_in), lag(lag_in) {}
+
+ bool operator==(const RoseInstrSomLeftfix &ri) const {
+ return queue == ri.queue && lag == ri.lag;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, queue, lag);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrSomLeftfix &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return queue == ri.queue && lag == ri.lag;
+ }
+};
+
+class RoseInstrSomFromReport
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_SOM_FROM_REPORT,
+ ROSE_STRUCT_SOM_FROM_REPORT,
+ RoseInstrSomFromReport> {
+public:
+ som_operation som;
+
+ RoseInstrSomFromReport() {
+ std::memset(&som, 0, sizeof(som));
+ }
+
+ bool operator==(const RoseInstrSomFromReport &ri) const {
+ return std::memcmp(&som, &ri.som, sizeof(som)) == 0;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, som.type, som.onmatch);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrSomFromReport &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return std::memcmp(&som, &ri.som, sizeof(som)) == 0;
+ }
+};
+
+class RoseInstrSomZero
+ : public RoseInstrBaseTrivial<ROSE_INSTR_SOM_ZERO, ROSE_STRUCT_SOM_ZERO,
+ RoseInstrSomZero> {
+public:
+ ~RoseInstrSomZero() override;
+};
+
+class RoseInstrTriggerInfix
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_TRIGGER_INFIX,
+ ROSE_STRUCT_TRIGGER_INFIX,
+ RoseInstrTriggerInfix> {
+public:
+ u8 cancel;
+ u32 queue;
+ u32 event;
+
+ RoseInstrTriggerInfix(u8 cancel_in, u32 queue_in, u32 event_in)
+ : cancel(cancel_in), queue(queue_in), event(event_in) {}
+
+ bool operator==(const RoseInstrTriggerInfix &ri) const {
+ return cancel == ri.cancel && queue == ri.queue && event == ri.event;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, cancel, queue, event);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrTriggerInfix &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return cancel == ri.cancel && queue == ri.queue && event == ri.event;
+ }
+};
+
+class RoseInstrTriggerSuffix
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_TRIGGER_SUFFIX,
+ ROSE_STRUCT_TRIGGER_SUFFIX,
+ RoseInstrTriggerSuffix> {
+public:
+ u32 queue;
+ u32 event;
+
+ RoseInstrTriggerSuffix(u32 queue_in, u32 event_in)
+ : queue(queue_in), event(event_in) {}
+
+ bool operator==(const RoseInstrTriggerSuffix &ri) const {
+ return queue == ri.queue && event == ri.event;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, queue, event);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrTriggerSuffix &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return queue == ri.queue && event == ri.event;
+ }
+};
+
+class RoseInstrDedupe
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_DEDUPE, ROSE_STRUCT_DEDUPE,
+ RoseInstrDedupe> {
+public:
+ u8 quash_som;
+ u32 dkey;
+ s32 offset_adjust;
+ const RoseInstruction *target;
+
+ RoseInstrDedupe(u8 quash_som_in, u32 dkey_in, s32 offset_adjust_in,
+ const RoseInstruction *target_in)
+ : quash_som(quash_som_in), dkey(dkey_in),
+ offset_adjust(offset_adjust_in), target(target_in) {}
+
+ bool operator==(const RoseInstrDedupe &ri) const {
+ return quash_som == ri.quash_som && dkey == ri.dkey &&
+ offset_adjust == ri.offset_adjust && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, quash_som, dkey, offset_adjust);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrDedupe &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return quash_som == ri.quash_som && dkey == ri.dkey &&
+ offset_adjust == ri.offset_adjust &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrDedupeSom
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_DEDUPE_SOM,
+ ROSE_STRUCT_DEDUPE_SOM,
+ RoseInstrDedupeSom> {
+public:
+ u8 quash_som;
+ u32 dkey;
+ s32 offset_adjust;
+ const RoseInstruction *target;
+
+ RoseInstrDedupeSom(u8 quash_som_in, u32 dkey_in, s32 offset_adjust_in,
+ const RoseInstruction *target_in)
+ : quash_som(quash_som_in), dkey(dkey_in),
+ offset_adjust(offset_adjust_in), target(target_in) {}
+
+ bool operator==(const RoseInstrDedupeSom &ri) const {
+ return quash_som == ri.quash_som && dkey == ri.dkey &&
+ offset_adjust == ri.offset_adjust && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, quash_som, dkey, offset_adjust);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrDedupeSom &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return quash_som == ri.quash_som && dkey == ri.dkey &&
+ offset_adjust == ri.offset_adjust &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrReportChain
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_CHAIN,
+ ROSE_STRUCT_REPORT_CHAIN,
+ RoseInstrReportChain> {
+public:
+ u32 event;
+ u64a top_squash_distance;
+
+ RoseInstrReportChain(u32 event_in, u32 top_squash_distance_in)
+ : event(event_in), top_squash_distance(top_squash_distance_in) {}
+
+ bool operator==(const RoseInstrReportChain &ri) const {
+ return event == ri.event &&
+ top_squash_distance == ri.top_squash_distance;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, event, top_squash_distance);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrReportChain &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return event == ri.event &&
+ top_squash_distance == ri.top_squash_distance;
+ }
+};
+
+class RoseInstrReportSomInt
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_SOM_INT,
+ ROSE_STRUCT_REPORT_SOM_INT,
+ RoseInstrReportSomInt> {
+public:
+ som_operation som;
+
+ RoseInstrReportSomInt() {
+ std::memset(&som, 0, sizeof(som));
+ }
+
+ bool operator==(const RoseInstrReportSomInt &ri) const {
+ return std::memcmp(&som, &ri.som, sizeof(som)) == 0;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, som.type, som.onmatch);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrReportSomInt &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return std::memcmp(&som, &ri.som, sizeof(som)) == 0;
+ }
+};
+
+class RoseInstrReportSomAware
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_SOM_AWARE,
+ ROSE_STRUCT_REPORT_SOM_AWARE,
+ RoseInstrReportSomAware> {
+public:
+ som_operation som;
+
+ RoseInstrReportSomAware() {
+ std::memset(&som, 0, sizeof(som));
+ }
+
+ bool operator==(const RoseInstrReportSomAware &ri) const {
+ return std::memcmp(&som, &ri.som, sizeof(som)) == 0;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, som.type, som.onmatch);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrReportSomAware &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return std::memcmp(&som, &ri.som, sizeof(som)) == 0;
+ }
+};
+
+class RoseInstrReport
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT, ROSE_STRUCT_REPORT,
+ RoseInstrReport> {
+public:
+ ReportID onmatch;
+ s32 offset_adjust;
+
+ RoseInstrReport(ReportID onmatch_in, s32 offset_adjust_in)
+ : onmatch(onmatch_in), offset_adjust(offset_adjust_in) {}
+
+ bool operator==(const RoseInstrReport &ri) const {
+ return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, onmatch, offset_adjust);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrReport &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust;
+ }
+};
+
+class RoseInstrReportExhaust
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_EXHAUST,
+ ROSE_STRUCT_REPORT_EXHAUST,
+ RoseInstrReportExhaust> {
+public:
+ ReportID onmatch;
+ s32 offset_adjust;
+ u32 ekey;
+
+ RoseInstrReportExhaust(ReportID onmatch_in, s32 offset_adjust_in,
+ u32 ekey_in)
+ : onmatch(onmatch_in), offset_adjust(offset_adjust_in), ekey(ekey_in) {}
+
+ bool operator==(const RoseInstrReportExhaust &ri) const {
+ return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust &&
+ ekey == ri.ekey;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, onmatch, offset_adjust, ekey);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrReportExhaust &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust &&
+ ekey == ri.ekey;
+ }
+};
+
+class RoseInstrReportSom
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_SOM,
+ ROSE_STRUCT_REPORT_SOM,
+ RoseInstrReportSom> {
+public:
+ ReportID onmatch;
+ s32 offset_adjust;
+
+ RoseInstrReportSom(ReportID onmatch_in, s32 offset_adjust_in)
+ : onmatch(onmatch_in), offset_adjust(offset_adjust_in) {}
+
+ bool operator==(const RoseInstrReportSom &ri) const {
+ return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, onmatch, offset_adjust);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrReportSom &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust;
+ }
+};
+
+class RoseInstrReportSomExhaust
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_SOM_EXHAUST,
+ ROSE_STRUCT_REPORT_SOM_EXHAUST,
+ RoseInstrReportSomExhaust> {
+public:
+ ReportID onmatch;
+ s32 offset_adjust;
+ u32 ekey;
+
+ RoseInstrReportSomExhaust(ReportID onmatch_in, s32 offset_adjust_in,
+ u32 ekey_in)
+ : onmatch(onmatch_in), offset_adjust(offset_adjust_in), ekey(ekey_in) {}
+
+ bool operator==(const RoseInstrReportSomExhaust &ri) const {
+ return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust &&
+ ekey == ri.ekey;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, onmatch, offset_adjust, ekey);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrReportSomExhaust &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust &&
+ ekey == ri.ekey;
+ }
+};
+
+class RoseInstrDedupeAndReport
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_DEDUPE_AND_REPORT,
+ ROSE_STRUCT_DEDUPE_AND_REPORT,
+ RoseInstrDedupeAndReport> {
+public:
+ u8 quash_som;
+ u32 dkey;
+ ReportID onmatch;
+ s32 offset_adjust;
+ const RoseInstruction *target;
+
+ RoseInstrDedupeAndReport(u8 quash_som_in, u32 dkey_in, ReportID onmatch_in,
+ s32 offset_adjust_in,
+ const RoseInstruction *target_in)
+ : quash_som(quash_som_in), dkey(dkey_in), onmatch(onmatch_in),
+ offset_adjust(offset_adjust_in), target(target_in) {}
+
+ bool operator==(const RoseInstrDedupeAndReport &ri) const {
+ return quash_som == ri.quash_som && dkey == ri.dkey &&
+ onmatch == ri.onmatch && offset_adjust == ri.offset_adjust &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, quash_som, dkey, onmatch, offset_adjust);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrDedupeAndReport &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return quash_som == ri.quash_som && dkey == ri.dkey &&
+ onmatch == ri.onmatch && offset_adjust == ri.offset_adjust &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrFinalReport
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_FINAL_REPORT,
+ ROSE_STRUCT_FINAL_REPORT,
+ RoseInstrFinalReport> {
+public:
+ ReportID onmatch;
+ s32 offset_adjust;
+
+ RoseInstrFinalReport(ReportID onmatch_in, s32 offset_adjust_in)
+ : onmatch(onmatch_in), offset_adjust(offset_adjust_in) {}
+
+ bool operator==(const RoseInstrFinalReport &ri) const {
+ return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, onmatch, offset_adjust);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrFinalReport &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust;
+ }
+};
+
+class RoseInstrCheckExhausted
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_EXHAUSTED,
+ ROSE_STRUCT_CHECK_EXHAUSTED,
+ RoseInstrCheckExhausted> {
+public:
+ u32 ekey;
+ const RoseInstruction *target;
+
+ RoseInstrCheckExhausted(u32 ekey_in, const RoseInstruction *target_in)
+ : ekey(ekey_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckExhausted &ri) const {
+ return ekey == ri.ekey && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, ekey);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckExhausted &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return ekey == ri.ekey &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckMinLength
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MIN_LENGTH,
+ ROSE_STRUCT_CHECK_MIN_LENGTH,
+ RoseInstrCheckMinLength> {
+public:
+ s32 end_adj;
+ u64a min_length;
+ const RoseInstruction *target;
+
+ RoseInstrCheckMinLength(s32 end_adj_in, u64a min_length_in,
+ const RoseInstruction *target_in)
+ : end_adj(end_adj_in), min_length(min_length_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckMinLength &ri) const {
+ return end_adj == ri.end_adj && min_length == ri.min_length &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, end_adj, min_length);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckMinLength &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return end_adj == ri.end_adj && min_length == ri.min_length &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrSetState
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_SET_STATE, ROSE_STRUCT_SET_STATE,
+ RoseInstrSetState> {
+public:
+ u32 index;
+
+ explicit RoseInstrSetState(u32 index_in) : index(index_in) {}
+
+ bool operator==(const RoseInstrSetState &ri) const {
+ return index == ri.index;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, index);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrSetState &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return index == ri.index;
+ }
+};
+
+class RoseInstrSetGroups
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_SET_GROUPS,
+ ROSE_STRUCT_SET_GROUPS,
+ RoseInstrSetGroups> {
+public:
+ rose_group groups;
+
+ explicit RoseInstrSetGroups(rose_group groups_in) : groups(groups_in) {}
+
+ bool operator==(const RoseInstrSetGroups &ri) const {
+ return groups == ri.groups;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, groups);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrSetGroups &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return groups == ri.groups;
+ }
+};
+
+class RoseInstrSquashGroups
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_SQUASH_GROUPS,
+ ROSE_STRUCT_SQUASH_GROUPS,
+ RoseInstrSquashGroups> {
+public:
+ rose_group groups;
+
+ explicit RoseInstrSquashGroups(rose_group groups_in) : groups(groups_in) {}
+
+ bool operator==(const RoseInstrSquashGroups &ri) const {
+ return groups == ri.groups;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, groups);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrSquashGroups &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return groups == ri.groups;
+ }
+};
+
+class RoseInstrCheckState
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_STATE,
+ ROSE_STRUCT_CHECK_STATE,
+ RoseInstrCheckState> {
+public:
+ u32 index;
+ const RoseInstruction *target;
+
+ RoseInstrCheckState(u32 index_in, const RoseInstruction *target_in)
+ : index(index_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckState &ri) const {
+ return index == ri.index && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, index);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckState &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return index == ri.index &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrSparseIterBegin
+ : public RoseInstrBase<ROSE_INSTR_SPARSE_ITER_BEGIN,
+ ROSE_STRUCT_SPARSE_ITER_BEGIN,
+ RoseInstrSparseIterBegin> {
+public:
+ u32 num_keys; // total number of multibit keys
+ std::vector<std::pair<u32, const RoseInstruction *>> jump_table;
+ const RoseInstruction *target;
+
+ RoseInstrSparseIterBegin(u32 num_keys_in,
+ const RoseInstruction *target_in)
+ : num_keys(num_keys_in), target(target_in) {}
+
+ bool operator==(const RoseInstrSparseIterBegin &ri) const {
+ return num_keys == ri.num_keys && jump_table == ri.jump_table &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ size_t v = hash_all(opcode, num_keys);
+ for (const u32 &key : jump_table | boost::adaptors::map_keys) {
+ hash_combine(v, key);
+ }
+ return v;
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ void update_target(const RoseInstruction *old_target,
+ const RoseInstruction *new_target) override {
+ if (target == old_target) {
+ target = new_target;
+ }
+ for (auto &jump : jump_table) {
+ if (jump.second == old_target) {
+ jump.second = new_target;
+ }
+ }
+ }
+
+ bool equiv_to(const RoseInstrSparseIterBegin &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ if (iter_offset != ri.iter_offset ||
+ offsets.at(target) != other_offsets.at(ri.target)) {
+ return false;
+ }
+ if (jump_table.size() != ri.jump_table.size()) {
+ return false;
+ }
+ auto it1 = jump_table.begin(), it2 = ri.jump_table.begin();
+ for (; it1 != jump_table.end(); ++it1, ++it2) {
+ if (it1->first != it2->first) {
+ return false;
+ }
+ if (offsets.at(it1->second) != other_offsets.at(it2->second)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+private:
+ friend class RoseInstrSparseIterNext;
+
+ // These variables allow us to use the same multibit iterator and jump
+ // table in subsequent SPARSE_ITER_NEXT write() operations.
+ mutable bool is_written = false;
+ mutable u32 iter_offset = 0;
+ mutable u32 jump_table_offset = 0;
+};
+
+class RoseInstrSparseIterNext
+ : public RoseInstrBase<ROSE_INSTR_SPARSE_ITER_NEXT,
+ ROSE_STRUCT_SPARSE_ITER_NEXT,
+ RoseInstrSparseIterNext> {
+public:
+ u32 state;
+ const RoseInstrSparseIterBegin *begin;
+ const RoseInstruction *target;
+
+ RoseInstrSparseIterNext(u32 state_in,
+ const RoseInstrSparseIterBegin *begin_in,
+ const RoseInstruction *target_in)
+ : state(state_in), begin(begin_in), target(target_in) {}
+
+ bool operator==(const RoseInstrSparseIterNext &ri) const {
+ return state == ri.state && begin == ri.begin && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, state);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ void update_target(const RoseInstruction *old_target,
+ const RoseInstruction *new_target) override {
+ if (target == old_target) {
+ target = new_target;
+ }
+ if (begin == old_target) {
+ assert(new_target->code() == ROSE_INSTR_SPARSE_ITER_BEGIN);
+ begin = static_cast<const RoseInstrSparseIterBegin *>(new_target);
+ }
+ }
+
+ bool equiv_to(const RoseInstrSparseIterNext &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return state == ri.state &&
+ offsets.at(begin) == other_offsets.at(ri.begin) &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrSparseIterAny
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_SPARSE_ITER_ANY,
+ ROSE_STRUCT_SPARSE_ITER_ANY,
+ RoseInstrSparseIterAny> {
+public:
+ u32 num_keys; // total number of multibit keys
+ std::vector<u32> keys;
+ const RoseInstruction *target;
+
+ RoseInstrSparseIterAny(u32 num_keys_in, std::vector<u32> keys_in,
+ const RoseInstruction *target_in)
+ : num_keys(num_keys_in), keys(std::move(keys_in)), target(target_in) {}
+
+ bool operator==(const RoseInstrSparseIterAny &ri) const {
+ return num_keys == ri.num_keys && keys == ri.keys &&
+ target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, num_keys, keys);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrSparseIterAny &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return num_keys == ri.num_keys && keys == ri.keys &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrEnginesEod
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_ENGINES_EOD,
+ ROSE_STRUCT_ENGINES_EOD,
+ RoseInstrEnginesEod> {
+public:
+ u32 iter_offset;
+
+ explicit RoseInstrEnginesEod(u32 iter_in) : iter_offset(iter_in) {}
+
+ bool operator==(const RoseInstrEnginesEod &ri) const {
+ return iter_offset == ri.iter_offset;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, iter_offset);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrEnginesEod &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return iter_offset == ri.iter_offset;
+ }
+};
+
+class RoseInstrSuffixesEod
+ : public RoseInstrBaseTrivial<ROSE_INSTR_SUFFIXES_EOD,
+ ROSE_STRUCT_SUFFIXES_EOD,
+ RoseInstrSuffixesEod> {
+public:
+ ~RoseInstrSuffixesEod() override;
+};
+
+class RoseInstrMatcherEod : public RoseInstrBaseTrivial<ROSE_INSTR_MATCHER_EOD,
+ ROSE_STRUCT_MATCHER_EOD,
+ RoseInstrMatcherEod> {
+public:
+ ~RoseInstrMatcherEod() override;
+};
+
+class RoseInstrCheckLongLit
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_LONG_LIT,
+ ROSE_STRUCT_CHECK_LONG_LIT,
+ RoseInstrCheckLongLit> {
+public:
+ std::string literal;
+ const RoseInstruction *target;
+
+ RoseInstrCheckLongLit(std::string literal_in,
+ const RoseInstruction *target_in)
+ : literal(std::move(literal_in)), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckLongLit &ri) const {
+ return literal == ri.literal && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, literal);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckLongLit &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return literal == ri.literal &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckLongLitNocase
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_LONG_LIT_NOCASE,
+ ROSE_STRUCT_CHECK_LONG_LIT_NOCASE,
+ RoseInstrCheckLongLitNocase> {
+public:
+ std::string literal;
+ const RoseInstruction *target;
+
+ RoseInstrCheckLongLitNocase(std::string literal_in,
+ const RoseInstruction *target_in)
+ : literal(std::move(literal_in)), target(target_in) {
+ upperString(literal);
+ }
+
+ bool operator==(const RoseInstrCheckLongLitNocase &ri) const {
+ return literal == ri.literal && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, literal);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckLongLitNocase &ri,
+ const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return literal == ri.literal &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckMedLit
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MED_LIT,
+ ROSE_STRUCT_CHECK_MED_LIT,
+ RoseInstrCheckMedLit> {
+public:
+ std::string literal;
+ const RoseInstruction *target;
+
+ explicit RoseInstrCheckMedLit(std::string literal_in,
+ const RoseInstruction *target_in)
+ : literal(std::move(literal_in)), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckMedLit &ri) const {
+ return literal == ri.literal && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, literal);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckMedLit &ri, const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return literal == ri.literal &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckMedLitNocase
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MED_LIT_NOCASE,
+ ROSE_STRUCT_CHECK_MED_LIT_NOCASE,
+ RoseInstrCheckMedLitNocase> {
+public:
+ std::string literal;
+ const RoseInstruction *target;
+
+ explicit RoseInstrCheckMedLitNocase(std::string literal_in,
+ const RoseInstruction *target_in)
+ : literal(std::move(literal_in)), target(target_in) {
+ upperString(literal);
+ }
+
+ bool operator==(const RoseInstrCheckMedLitNocase &ri) const {
+ return literal == ri.literal && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, literal);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckMedLitNocase &ri,
+ const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return literal == ri.literal &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrClearWorkDone
+ : public RoseInstrBaseTrivial<ROSE_INSTR_CLEAR_WORK_DONE,
+ ROSE_STRUCT_CLEAR_WORK_DONE,
+ RoseInstrClearWorkDone> {
+public:
+ ~RoseInstrClearWorkDone() override;
+};
+
+class RoseInstrMultipathLookaround
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_MULTIPATH_LOOKAROUND,
+ ROSE_STRUCT_MULTIPATH_LOOKAROUND,
+ RoseInstrMultipathLookaround> {
+public:
+ std::vector<std::vector<LookEntry>> multi_look;
+ s32 last_start;
+ std::array<u8, 16> start_mask;
+ const RoseInstruction *target;
+
+ RoseInstrMultipathLookaround(std::vector<std::vector<LookEntry>> ml,
+ s32 last_start_in,
+ std::array<u8, 16> start_mask_in,
+ const RoseInstruction *target_in)
+ : multi_look(std::move(ml)), last_start(last_start_in),
+ start_mask(std::move(start_mask_in)), target(target_in) {}
+
+ bool operator==(const RoseInstrMultipathLookaround &ri) const {
+ return multi_look == ri.multi_look && last_start == ri.last_start
+ && start_mask == ri.start_mask && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, multi_look, last_start, start_mask);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrMultipathLookaround &ri,
+ const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return multi_look == ri.multi_look && last_start == ri.last_start
+ && start_mask == ri.start_mask
+ && offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckMultipathShufti16x8
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MULTIPATH_SHUFTI_16x8,
+ ROSE_STRUCT_CHECK_MULTIPATH_SHUFTI_16x8,
+ RoseInstrCheckMultipathShufti16x8> {
+public:
+ std::array<u8, 32> nib_mask;
+ std::array<u8, 64> bucket_select_mask;
+ std::array<u8, 64> data_select_mask;
+ u16 hi_bits_mask;
+ u16 lo_bits_mask;
+ u16 neg_mask;
+ s32 base_offset;
+ s32 last_start;
+ const RoseInstruction *target;
+
+ RoseInstrCheckMultipathShufti16x8(std::array<u8, 32> nib_mask_in,
+ std::array<u8, 64> bucket_select_mask_in,
+ std::array<u8, 64> data_select_mask_in,
+ u16 hi_bits_mask_in, u16 lo_bits_mask_in,
+ u16 neg_mask_in, s32 base_offset_in,
+ s32 last_start_in,
+ const RoseInstruction *target_in)
+ : nib_mask(std::move(nib_mask_in)),
+ bucket_select_mask(std::move(bucket_select_mask_in)),
+ data_select_mask(std::move(data_select_mask_in)),
+ hi_bits_mask(hi_bits_mask_in), lo_bits_mask(lo_bits_mask_in),
+ neg_mask(neg_mask_in), base_offset(base_offset_in),
+ last_start(last_start_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckMultipathShufti16x8 &ri) const {
+ return nib_mask == ri.nib_mask &&
+ bucket_select_mask == ri.bucket_select_mask &&
+ data_select_mask == ri.data_select_mask &&
+ hi_bits_mask == ri.hi_bits_mask &&
+ lo_bits_mask == ri.lo_bits_mask &&
+ neg_mask == ri.neg_mask && base_offset == ri.base_offset &&
+ last_start == ri.last_start && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, nib_mask, bucket_select_mask, data_select_mask,
+ hi_bits_mask, lo_bits_mask, neg_mask, base_offset,
+ last_start);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckMultipathShufti16x8 &ri,
+ const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return nib_mask == ri.nib_mask &&
+ bucket_select_mask == ri.bucket_select_mask &&
+ data_select_mask == ri.data_select_mask &&
+ hi_bits_mask == ri.hi_bits_mask &&
+ lo_bits_mask == ri.lo_bits_mask && neg_mask == ri.neg_mask &&
+ base_offset == ri.base_offset && last_start == ri.last_start &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckMultipathShufti32x8
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MULTIPATH_SHUFTI_32x8,
+ ROSE_STRUCT_CHECK_MULTIPATH_SHUFTI_32x8,
+ RoseInstrCheckMultipathShufti32x8> {
+public:
+ std::array<u8, 32> hi_mask;
+ std::array<u8, 32> lo_mask;
+ std::array<u8, 64> bucket_select_mask;
+ std::array<u8, 64> data_select_mask;
+ u32 hi_bits_mask;
+ u32 lo_bits_mask;
+ u32 neg_mask;
+ s32 base_offset;
+ s32 last_start;
+ const RoseInstruction *target;
+
+ RoseInstrCheckMultipathShufti32x8(std::array<u8, 32> hi_mask_in,
+ std::array<u8, 32> lo_mask_in,
+ std::array<u8, 64> bucket_select_mask_in,
+ std::array<u8, 64> data_select_mask_in,
+ u32 hi_bits_mask_in, u32 lo_bits_mask_in,
+ u32 neg_mask_in, s32 base_offset_in,
+ s32 last_start_in,
+ const RoseInstruction *target_in)
+ : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)),
+ bucket_select_mask(std::move(bucket_select_mask_in)),
+ data_select_mask(std::move(data_select_mask_in)),
+ hi_bits_mask(hi_bits_mask_in), lo_bits_mask(lo_bits_mask_in),
+ neg_mask(neg_mask_in), base_offset(base_offset_in),
+ last_start(last_start_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckMultipathShufti32x8 &ri) const {
+ return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
+ bucket_select_mask == ri.bucket_select_mask &&
+ data_select_mask == ri.data_select_mask &&
+ hi_bits_mask == ri.hi_bits_mask &&
+ lo_bits_mask == ri.lo_bits_mask &&
+ neg_mask == ri.neg_mask && base_offset == ri.base_offset &&
+ last_start == ri.last_start && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask,
+ data_select_mask, hi_bits_mask, lo_bits_mask, neg_mask,
+ base_offset, last_start);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckMultipathShufti32x8 &ri,
+ const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
+ bucket_select_mask == ri.bucket_select_mask &&
+ data_select_mask == ri.data_select_mask &&
+ hi_bits_mask == ri.hi_bits_mask &&
+ lo_bits_mask == ri.lo_bits_mask && neg_mask == ri.neg_mask &&
+ base_offset == ri.base_offset && last_start == ri.last_start &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckMultipathShufti32x16
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MULTIPATH_SHUFTI_32x16,
+ ROSE_STRUCT_CHECK_MULTIPATH_SHUFTI_32x16,
+ RoseInstrCheckMultipathShufti32x16> {
+public:
+ std::array<u8, 32> hi_mask;
+ std::array<u8, 32> lo_mask;
+ std::array<u8, 64> bucket_select_mask_hi;
+ std::array<u8, 64> bucket_select_mask_lo;
+ std::array<u8, 64> data_select_mask;
+ u32 hi_bits_mask;
+ u32 lo_bits_mask;
+ u32 neg_mask;
+ s32 base_offset;
+ s32 last_start;
+ const RoseInstruction *target;
+
+ RoseInstrCheckMultipathShufti32x16(std::array<u8, 32> hi_mask_in,
+ std::array<u8, 32> lo_mask_in,
+ std::array<u8, 64> bucket_select_mask_hi_in,
+ std::array<u8, 64> bucket_select_mask_lo_in,
+ std::array<u8, 64> data_select_mask_in,
+ u32 hi_bits_mask_in, u32 lo_bits_mask_in,
+ u32 neg_mask_in, s32 base_offset_in,
+ s32 last_start_in,
+ const RoseInstruction *target_in)
+ : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)),
+ bucket_select_mask_hi(std::move(bucket_select_mask_hi_in)),
+ bucket_select_mask_lo(std::move(bucket_select_mask_lo_in)),
+ data_select_mask(std::move(data_select_mask_in)),
+ hi_bits_mask(hi_bits_mask_in), lo_bits_mask(lo_bits_mask_in),
+ neg_mask(neg_mask_in), base_offset(base_offset_in),
+ last_start(last_start_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckMultipathShufti32x16 &ri) const {
+ return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
+ bucket_select_mask_hi == ri.bucket_select_mask_hi &&
+ bucket_select_mask_lo == ri.bucket_select_mask_lo &&
+ data_select_mask == ri.data_select_mask &&
+ hi_bits_mask == ri.hi_bits_mask &&
+ lo_bits_mask == ri.lo_bits_mask &&
+ neg_mask == ri.neg_mask && base_offset == ri.base_offset &&
+ last_start == ri.last_start && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask_hi,
+ bucket_select_mask_lo, data_select_mask, hi_bits_mask,
+ lo_bits_mask, neg_mask, base_offset, last_start);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckMultipathShufti32x16 &ri,
+ const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
+ bucket_select_mask_hi == ri.bucket_select_mask_hi &&
+ bucket_select_mask_lo == ri.bucket_select_mask_lo &&
+ data_select_mask == ri.data_select_mask &&
+ hi_bits_mask == ri.hi_bits_mask &&
+ lo_bits_mask == ri.lo_bits_mask && neg_mask == ri.neg_mask &&
+ base_offset == ri.base_offset && last_start == ri.last_start &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrCheckMultipathShufti64
+ : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MULTIPATH_SHUFTI_64,
+ ROSE_STRUCT_CHECK_MULTIPATH_SHUFTI_64,
+ RoseInstrCheckMultipathShufti64> {
+public:
+ std::array<u8, 32> hi_mask;
+ std::array<u8, 32> lo_mask;
+ std::array<u8, 64> bucket_select_mask;
+ std::array<u8, 64> data_select_mask;
+ u64a hi_bits_mask;
+ u64a lo_bits_mask;
+ u64a neg_mask;
+ s32 base_offset;
+ s32 last_start;
+ const RoseInstruction *target;
+
+ RoseInstrCheckMultipathShufti64(std::array<u8, 32> hi_mask_in,
+ std::array<u8, 32> lo_mask_in,
+ std::array<u8, 64> bucket_select_mask_in,
+ std::array<u8, 64> data_select_mask_in,
+ u64a hi_bits_mask_in, u64a lo_bits_mask_in,
+ u64a neg_mask_in, s32 base_offset_in,
+ s32 last_start_in,
+ const RoseInstruction *target_in)
+ : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)),
+ bucket_select_mask(std::move(bucket_select_mask_in)),
+ data_select_mask(std::move(data_select_mask_in)),
+ hi_bits_mask(hi_bits_mask_in), lo_bits_mask(lo_bits_mask_in),
+ neg_mask(neg_mask_in), base_offset(base_offset_in),
+ last_start(last_start_in), target(target_in) {}
+
+ bool operator==(const RoseInstrCheckMultipathShufti64 &ri) const {
+ return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
+ bucket_select_mask == ri.bucket_select_mask &&
+ data_select_mask == ri.data_select_mask &&
+ hi_bits_mask == ri.hi_bits_mask &&
+ lo_bits_mask == ri.lo_bits_mask &&
+ neg_mask == ri.neg_mask && base_offset == ri.base_offset &&
+ last_start == ri.last_start && target == ri.target;
+ }
+
+ size_t hash() const override {
+ return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask,
+ data_select_mask, hi_bits_mask, lo_bits_mask, neg_mask,
+ base_offset, last_start);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrCheckMultipathShufti64 &ri,
+ const OffsetMap &offsets,
+ const OffsetMap &other_offsets) const {
+ return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask &&
+ bucket_select_mask == ri.bucket_select_mask &&
+ data_select_mask == ri.data_select_mask &&
+ hi_bits_mask == ri.hi_bits_mask &&
+ lo_bits_mask == ri.lo_bits_mask && neg_mask == ri.neg_mask &&
+ base_offset == ri.base_offset && last_start == ri.last_start &&
+ offsets.at(target) == other_offsets.at(ri.target);
+ }
+};
+
+class RoseInstrIncludedJump
+ : public RoseInstrBaseNoTargets<ROSE_INSTR_INCLUDED_JUMP,
+ ROSE_STRUCT_INCLUDED_JUMP,
+ RoseInstrIncludedJump> {
+public:
+ u32 child_offset;
+ u8 squash;
+
+ RoseInstrIncludedJump(u32 child_offset_in, u8 squash_in)
+ : child_offset(child_offset_in), squash(squash_in) {}
+
+ bool operator==(const RoseInstrIncludedJump &ri) const {
+ return child_offset == ri.child_offset && squash == ri.squash;
+ }
+
+ size_t hash() const override {
+ return hash_all(static_cast<int>(opcode), child_offset, squash);
+ }
+
+ void write(void *dest, RoseEngineBlob &blob,
+ const OffsetMap &offset_map) const override;
+
+ bool equiv_to(const RoseInstrIncludedJump &ri, const OffsetMap &,
+ const OffsetMap &) const {
+ return child_offset == ri.child_offset && squash == ri.squash;
+ }
+};
+
class RoseInstrSetLogical
: public RoseInstrBaseNoTargets<ROSE_INSTR_SET_LOGICAL,
ROSE_STRUCT_SET_LOGICAL,
@@ -2380,12 +2380,12 @@ public:
}
};
-class RoseInstrEnd
- : public RoseInstrBaseTrivial<ROSE_INSTR_END, ROSE_STRUCT_END,
- RoseInstrEnd> {
-public:
- ~RoseInstrEnd() override;
-};
-
-}
-#endif
+class RoseInstrEnd
+ : public RoseInstrBaseTrivial<ROSE_INSTR_END, ROSE_STRUCT_END,
+ RoseInstrEnd> {
+public:
+ ~RoseInstrEnd() override;
+};
+
+}
+#endif