xref: /llvm-project/lldb/unittests/Target/DynamicRegisterInfoTest.cpp (revision 1bd258fd4e2c94d35cdda07b4ca64a2de8d4a047)
1214054f7SMichał Górny //===-- DynamicRegisterInfoTest.cpp ---------------------------------------===//
2214054f7SMichał Górny //
3214054f7SMichał Górny // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4214054f7SMichał Górny // See https://llvm.org/LICENSE.txt for license information.
5214054f7SMichał Górny // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6214054f7SMichał Górny //
7214054f7SMichał Górny //===----------------------------------------------------------------------===//
8214054f7SMichał Górny 
9214054f7SMichał Górny #include "gmock/gmock.h"
10214054f7SMichał Górny #include "gtest/gtest.h"
11214054f7SMichał Górny 
12214054f7SMichał Górny #include "lldb/Target/DynamicRegisterInfo.h"
13214054f7SMichał Górny #include "lldb/Utility/ArchSpec.h"
14214054f7SMichał Górny 
151afda54fSMichał Górny #include <functional>
161afda54fSMichał Górny 
17214054f7SMichał Górny using namespace lldb_private;
18214054f7SMichał Górny 
regs_to_vector(uint32_t * regs)19214054f7SMichał Górny static std::vector<uint32_t> regs_to_vector(uint32_t *regs) {
20214054f7SMichał Górny   std::vector<uint32_t> ret;
21214054f7SMichał Górny   if (regs) {
22214054f7SMichał Górny     while (*regs != LLDB_INVALID_REGNUM)
23214054f7SMichał Górny       ret.push_back(*regs++);
24214054f7SMichał Górny   }
25214054f7SMichał Górny   return ret;
26214054f7SMichał Górny }
27214054f7SMichał Górny 
281afda54fSMichał Górny class DynamicRegisterInfoRegisterTest : public ::testing::Test {
291afda54fSMichał Górny protected:
301afda54fSMichał Górny   std::vector<DynamicRegisterInfo::Register> m_regs;
3166063277SMichał Górny   DynamicRegisterInfo m_dyninfo;
321afda54fSMichał Górny 
AddTestRegister(const char * name,const char * group,uint32_t byte_size,std::function<void (const DynamicRegisterInfo::Register &)> adder,std::vector<uint32_t> value_regs={},std::vector<uint32_t> invalidate_regs={})331afda54fSMichał Górny   uint32_t AddTestRegister(
341afda54fSMichał Górny       const char *name, const char *group, uint32_t byte_size,
351afda54fSMichał Górny       std::function<void(const DynamicRegisterInfo::Register &)> adder,
361afda54fSMichał Górny       std::vector<uint32_t> value_regs = {},
371afda54fSMichał Górny       std::vector<uint32_t> invalidate_regs = {}) {
3866063277SMichał Górny     DynamicRegisterInfo::Register new_reg{ConstString(name),
3966063277SMichał Górny                                           ConstString(),
4066063277SMichał Górny                                           ConstString(group),
4166063277SMichał Górny                                           byte_size,
4266063277SMichał Górny                                           LLDB_INVALID_INDEX32,
4366063277SMichał Górny                                           lldb::eEncodingUint,
4466063277SMichał Górny                                           lldb::eFormatUnsigned,
4566063277SMichał Górny                                           LLDB_INVALID_REGNUM,
4666063277SMichał Górny                                           LLDB_INVALID_REGNUM,
4766063277SMichał Górny                                           LLDB_INVALID_REGNUM,
4866063277SMichał Górny                                           static_cast<uint32_t>(m_regs.size()),
4966063277SMichał Górny                                           value_regs,
501afda54fSMichał Górny                                           invalidate_regs};
511afda54fSMichał Górny     adder(new_reg);
521afda54fSMichał Górny     return m_regs.size() - 1;
531afda54fSMichał Górny   }
541afda54fSMichał Górny 
ExpectInRegs(uint32_t reg_num,const char * reg_name,std::vector<uint32_t> value_regs,std::vector<uint32_t> invalidate_regs)551afda54fSMichał Górny   void ExpectInRegs(uint32_t reg_num, const char *reg_name,
561afda54fSMichał Górny                     std::vector<uint32_t> value_regs,
571afda54fSMichał Górny                     std::vector<uint32_t> invalidate_regs) {
581afda54fSMichał Górny     ASSERT_GT(m_regs.size(), reg_num);
591afda54fSMichał Górny 
601afda54fSMichał Górny     const DynamicRegisterInfo::Register &reg = m_regs[reg_num];
611afda54fSMichał Górny     ConstString expected_reg_name{reg_name};
621afda54fSMichał Górny     EXPECT_EQ(reg.name, expected_reg_name);
631afda54fSMichał Górny     EXPECT_EQ(reg.value_regs, value_regs);
641afda54fSMichał Górny     EXPECT_EQ(reg.invalidate_regs, invalidate_regs);
651afda54fSMichał Górny   }
6666063277SMichał Górny 
ExpectInDynInfo(uint32_t reg_num,const char * reg_name,uint32_t byte_offset,std::vector<uint32_t> value_regs={},std::vector<uint32_t> invalidate_regs={})6766063277SMichał Górny   void ExpectInDynInfo(uint32_t reg_num, const char *reg_name,
6866063277SMichał Górny                        uint32_t byte_offset,
6966063277SMichał Górny                        std::vector<uint32_t> value_regs = {},
7066063277SMichał Górny                        std::vector<uint32_t> invalidate_regs = {}) {
7166063277SMichał Górny     const RegisterInfo *reg = m_dyninfo.GetRegisterInfoAtIndex(reg_num);
7266063277SMichał Górny     ASSERT_NE(reg, nullptr);
7366063277SMichał Górny     EXPECT_STREQ(reg->name, reg_name);
7466063277SMichał Górny     EXPECT_EQ(reg->byte_offset, byte_offset);
7566063277SMichał Górny     EXPECT_THAT(regs_to_vector(reg->value_regs), value_regs);
7666063277SMichał Górny     EXPECT_THAT(regs_to_vector(reg->invalidate_regs), invalidate_regs);
7766063277SMichał Górny   }
781afda54fSMichał Górny };
791afda54fSMichał Górny 
801afda54fSMichał Górny #define EXPECT_IN_REGS(reg, ...)                                               \
811afda54fSMichał Górny   {                                                                            \
821afda54fSMichał Górny     SCOPED_TRACE("at register " #reg);                                         \
831afda54fSMichał Górny     ExpectInRegs(reg, #reg, __VA_ARGS__);                                      \
841afda54fSMichał Górny   }
851afda54fSMichał Górny 
8666063277SMichał Górny #define EXPECT_IN_DYNINFO(reg, ...)                                            \
8766063277SMichał Górny   {                                                                            \
8866063277SMichał Górny     SCOPED_TRACE("at register " #reg);                                         \
8966063277SMichał Górny     ExpectInDynInfo(reg, #reg, __VA_ARGS__);                                   \
9066063277SMichał Górny   }
9166063277SMichał Górny 
TEST_F(DynamicRegisterInfoRegisterTest,addSupplementaryRegister)921afda54fSMichał Górny TEST_F(DynamicRegisterInfoRegisterTest, addSupplementaryRegister) {
93214054f7SMichał Górny   // Add a base register
941afda54fSMichał Górny   uint32_t rax = AddTestRegister(
951afda54fSMichał Górny       "rax", "group", 8,
961afda54fSMichał Górny       [this](const DynamicRegisterInfo::Register &r) { m_regs.push_back(r); });
97214054f7SMichał Górny 
981afda54fSMichał Górny   // Add supplementary registers
991afda54fSMichał Górny   auto suppl_adder = [this](const DynamicRegisterInfo::Register &r) {
1001afda54fSMichał Górny     addSupplementaryRegister(m_regs, r);
101214054f7SMichał Górny   };
1021afda54fSMichał Górny   uint32_t eax = AddTestRegister("eax", "supplementary", 4, suppl_adder, {rax});
1031afda54fSMichał Górny   uint32_t ax = AddTestRegister("ax", "supplementary", 2, suppl_adder, {rax});
104*0d1705a9SMichał Górny   uint32_t ah = AddTestRegister("ah", "supplementary", 1, suppl_adder, {rax});
1051afda54fSMichał Górny   uint32_t al = AddTestRegister("al", "supplementary", 1, suppl_adder, {rax});
106*0d1705a9SMichał Górny   m_regs[ah].value_reg_offset = 1;
107214054f7SMichał Górny 
108*0d1705a9SMichał Górny   EXPECT_IN_REGS(rax, {}, {eax, ax, ah, al});
109*0d1705a9SMichał Górny   EXPECT_IN_REGS(eax, {rax}, {rax, ax, ah, al});
110*0d1705a9SMichał Górny   EXPECT_IN_REGS(ax, {rax}, {rax, eax, ah, al});
111*0d1705a9SMichał Górny   EXPECT_IN_REGS(ah, {rax}, {rax, eax, ax, al});
112*0d1705a9SMichał Górny   EXPECT_IN_REGS(al, {rax}, {rax, eax, ax, ah});
113*0d1705a9SMichał Górny 
114*0d1705a9SMichał Górny   EXPECT_EQ(m_dyninfo.SetRegisterInfo(std::move(m_regs), ArchSpec()),
115*0d1705a9SMichał Górny             m_regs.size());
116*0d1705a9SMichał Górny   EXPECT_IN_DYNINFO(rax, 0, {}, {eax, ax, ah, al});
117*0d1705a9SMichał Górny   EXPECT_IN_DYNINFO(eax, 0, {rax}, {rax, ax, ah, al});
118*0d1705a9SMichał Górny   EXPECT_IN_DYNINFO(ax, 0, {rax}, {rax, eax, ah, al});
119*0d1705a9SMichał Górny   EXPECT_IN_DYNINFO(ah, 1, {rax}, {rax, eax, ax, al});
120*0d1705a9SMichał Górny   EXPECT_IN_DYNINFO(al, 0, {rax}, {rax, eax, ax, ah});
121214054f7SMichał Górny }
12266063277SMichał Górny 
TEST_F(DynamicRegisterInfoRegisterTest,SetRegisterInfo)12366063277SMichał Górny TEST_F(DynamicRegisterInfoRegisterTest, SetRegisterInfo) {
12466063277SMichał Górny   auto adder = [this](const DynamicRegisterInfo::Register &r) {
12566063277SMichał Górny     m_regs.push_back(r);
12666063277SMichał Górny   };
12766063277SMichał Górny   // Add regular registers
12866063277SMichał Górny   uint32_t b1 = AddTestRegister("b1", "base", 8, adder);
12966063277SMichał Górny   uint32_t b2 = AddTestRegister("b2", "other", 8, adder);
13066063277SMichał Górny 
13166063277SMichał Górny   // Add a few sub-registers
13266063277SMichał Górny   uint32_t s1 = AddTestRegister("s1", "base", 4, adder, {b1});
13366063277SMichał Górny   uint32_t s2 = AddTestRegister("s2", "other", 4, adder, {b2});
13466063277SMichał Górny 
13566063277SMichał Górny   // Add a register with invalidate_regs
13666063277SMichał Górny   uint32_t i1 = AddTestRegister("i1", "third", 8, adder, {}, {b1});
13766063277SMichał Górny 
13866063277SMichał Górny   // Add a register with indirect invalidate regs to be expanded
13966063277SMichał Górny   // TODO: why is it done conditionally to value_regs?
14066063277SMichał Górny   uint32_t i2 = AddTestRegister("i2", "third", 4, adder, {b2}, {i1});
14166063277SMichał Górny 
14266063277SMichał Górny   EXPECT_EQ(m_dyninfo.SetRegisterInfo(std::move(m_regs), ArchSpec()),
14366063277SMichał Górny             m_regs.size());
14466063277SMichał Górny   EXPECT_IN_DYNINFO(b1, 0, {}, {});
14566063277SMichał Górny   EXPECT_IN_DYNINFO(b2, 8, {}, {});
14666063277SMichał Górny   EXPECT_IN_DYNINFO(s1, 0, {b1}, {});
14766063277SMichał Górny   EXPECT_IN_DYNINFO(s2, 8, {b2}, {});
14866063277SMichał Górny   EXPECT_IN_DYNINFO(i1, 16, {}, {b1});
14966063277SMichał Górny   EXPECT_IN_DYNINFO(i2, 8, {b2}, {b1, i1});
15066063277SMichał Górny }
151