diff options
author | Ivan Blinkov <ivan@blinkov.ru> | 2022-02-10 16:47:11 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:47:11 +0300 |
commit | 5b283123c882433dafbaf6b338adeea16c1a0ea0 (patch) | |
tree | 339adc63bce23800021202ae4a8328a843dc447a /contrib/libs/hyperscan/src/rose/rose_build_instructions.h | |
parent | 1aeb9a455974457866f78722ad98114bafc84e8a (diff) | |
download | ydb-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.h | 4308 |
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 |