Index: lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h =================================================================== --- lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h +++ lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h @@ -32,22 +32,30 @@ llvm::Optional ReadU32(EmulateInstructionRISCV &emulator); }; +#define DERIVE_EQ(NAME) \ + bool operator==(const NAME &r) const { \ + return std::memcmp(this, &r, sizeof(NAME)) == 0; \ + } + #define I_TYPE_INST(NAME) \ struct NAME { \ Rd rd; \ Rs rs1; \ uint32_t imm; \ + DERIVE_EQ(NAME); \ } #define S_TYPE_INST(NAME) \ struct NAME { \ Rs rs1; \ Rs rs2; \ uint32_t imm; \ + DERIVE_EQ(NAME); \ } #define U_TYPE_INST(NAME) \ struct NAME { \ Rd rd; \ uint32_t imm; \ + DERIVE_EQ(NAME); \ } /// The memory layout are the same in our code. #define J_TYPE_INST(NAME) U_TYPE_INST(NAME) @@ -56,22 +64,26 @@ Rd rd; \ Rs rs1; \ Rs rs2; \ + DERIVE_EQ(NAME); \ } #define R_SHAMT_TYPE_INST(NAME) \ struct NAME { \ Rd rd; \ Rs rs1; \ uint32_t shamt; \ + DERIVE_EQ(NAME); \ } #define R_RS1_TYPE_INST(NAME) \ struct NAME { \ Rd rd; \ Rs rs1; \ + DERIVE_EQ(NAME); \ } /// The `inst` fields are used for debugging. #define INVALID_INST(NAME) \ struct NAME { \ uint32_t inst; \ + DERIVE_EQ(NAME); \ } // RV32I instructions (The base integer ISA) @@ -80,6 +92,7 @@ Rs rs2; uint32_t imm; uint32_t funct3; + DERIVE_EQ(B); }; U_TYPE_INST(LUI); U_TYPE_INST(AUIPC); @@ -207,5 +220,16 @@ constexpr uint32_t DecodeRS1(uint32_t inst) { return (inst & 0xF8000) >> 15; } constexpr uint32_t DecodeRS2(uint32_t inst) { return (inst & 0x1F00000) >> 20; } +#undef R_TYPE_INST +#undef R_SHAMT_TYPE_INST +#undef R_RS1_TYPE_INST +#undef I_TYPE_INST +#undef S_TYPE_INST +#undef B_TYPE_INST +#undef U_TYPE_INST +#undef J_TYPE_INST +#undef INVALID_INST +#undef DERIVE_EQ + } // namespace lldb_private #endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H Index: lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp =================================================================== --- lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp +++ lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp @@ -261,25 +261,6 @@ RISCVInst inst_type; }; -bool compareInst(const RISCVInst &lhs, const RISCVInst &rhs) { - if (lhs.index() != rhs.index()) - return false; - return std::visit( - [&](auto &&L) { - return std::visit( - [&](auto &&R) { - // guaranteed by - // 1. lhs.index() == rhs.index() - // (they are the same instruction type) - // 2. all instruction representations are plain data objects - // consisting of primitive types. - return std::memcmp(&L, &R, sizeof(L)) == 0; - }, - rhs); - }, - lhs); -} - TEST_F(RISCVEmulatorTester, TestCDecode) { std::vector tests = { {0x0000, INVALID{0x0000}}, @@ -334,7 +315,7 @@ for (auto i : tests) { auto decode = this->Decode(i.inst); ASSERT_TRUE(decode.has_value()); - ASSERT_TRUE(compareInst(decode->decoded, i.inst_type)); + ASSERT_EQ(decode->decoded, i.inst_type); } }