Skip to content

[lldb] Add a single bit constructor for RegisterFlags::Field #69315

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lldb/include/lldb/Target/RegisterFlags.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@ class RegisterFlags {
public:
class Field {
public:
/// Where start is the least significant bit and end is the most
/// significant bit. The start bit must be <= the end bit.
Field(std::string name, unsigned start, unsigned end)
: m_name(std::move(name)), m_start(start), m_end(end) {
assert(m_start <= m_end && "Start bit must be <= end bit.");
}

/// Construct a field that occupies a single bit.
Field(std::string name, unsigned bit_position)
: m_name(std::move(name)), m_start(bit_position), m_end(bit_position) {}

/// Get size of the field in bits. Will always be at least 1.
unsigned GetSizeInBits() const { return m_end - m_start + 1; }

Expand Down
35 changes: 19 additions & 16 deletions lldb/unittests/Target/RegisterFlagsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ using namespace lldb;
TEST(RegisterFlagsTest, Field) {
// We assume that start <= end is always true, so that is not tested here.

RegisterFlags::Field f1("abc", 0, 0);
RegisterFlags::Field f1("abc", 0);
ASSERT_EQ(f1.GetName(), "abc");
// start == end means a 1 bit field.
ASSERT_EQ(f1.GetSizeInBits(), (unsigned)1);
Expand Down Expand Up @@ -51,11 +51,15 @@ static RegisterFlags::Field make_field(unsigned start, unsigned end) {
return RegisterFlags::Field("", start, end);
}

static RegisterFlags::Field make_field(unsigned bit) {
return RegisterFlags::Field("", bit);
}

TEST(RegisterFlagsTest, FieldOverlaps) {
// Single bit fields
ASSERT_FALSE(make_field(0, 0).Overlaps(make_field(1, 1)));
ASSERT_TRUE(make_field(1, 1).Overlaps(make_field(1, 1)));
ASSERT_FALSE(make_field(1, 1).Overlaps(make_field(3, 3)));
ASSERT_FALSE(make_field(0, 0).Overlaps(make_field(1)));
ASSERT_TRUE(make_field(1, 1).Overlaps(make_field(1)));
ASSERT_FALSE(make_field(1, 1).Overlaps(make_field(3)));

ASSERT_TRUE(make_field(0, 1).Overlaps(make_field(1, 2)));
ASSERT_TRUE(make_field(1, 2).Overlaps(make_field(0, 1)));
Expand All @@ -71,13 +75,13 @@ TEST(RegisterFlagsTest, PaddingDistance) {
// (start bit is higher) field first and that they do not overlap.

// [field 1][field 2]
ASSERT_EQ(make_field(1, 1).PaddingDistance(make_field(0, 0)), 0ULL);
ASSERT_EQ(make_field(1, 1).PaddingDistance(make_field(0)), 0ULL);
// [field 1][..][field 2]
ASSERT_EQ(make_field(2, 2).PaddingDistance(make_field(0, 0)), 1ULL);
ASSERT_EQ(make_field(2, 2).PaddingDistance(make_field(0)), 1ULL);
// [field 1][field 1][field 2]
ASSERT_EQ(make_field(1, 2).PaddingDistance(make_field(0, 0)), 0ULL);
ASSERT_EQ(make_field(1, 2).PaddingDistance(make_field(0)), 0ULL);
// [field 1][30 bits free][field 2]
ASSERT_EQ(make_field(31, 31).PaddingDistance(make_field(0, 0)), 30ULL);
ASSERT_EQ(make_field(31, 31).PaddingDistance(make_field(0)), 30ULL);
}

static void test_padding(const std::vector<RegisterFlags::Field> &fields,
Expand All @@ -99,18 +103,18 @@ TEST(RegisterFlagsTest, RegisterFlagsPadding) {

// Needs padding in between the fields, single bit.
test_padding({make_field(17, 31), make_field(0, 15)},
{make_field(17, 31), make_field(16, 16), make_field(0, 15)});
{make_field(17, 31), make_field(16), make_field(0, 15)});
// Multiple bits of padding.
test_padding({make_field(17, 31), make_field(0, 14)},
{make_field(17, 31), make_field(15, 16), make_field(0, 14)});

// Padding before first field, single bit.
test_padding({make_field(0, 30)}, {make_field(31, 31), make_field(0, 30)});
test_padding({make_field(0, 30)}, {make_field(31), make_field(0, 30)});
// Multiple bits.
test_padding({make_field(0, 15)}, {make_field(16, 31), make_field(0, 15)});

// Padding after last field, single bit.
test_padding({make_field(1, 31)}, {make_field(1, 31), make_field(0, 0)});
test_padding({make_field(1, 31)}, {make_field(1, 31), make_field(0)});
// Multiple bits.
test_padding({make_field(2, 31)}, {make_field(2, 31), make_field(0, 1)});

Expand All @@ -132,9 +136,8 @@ TEST(RegisterFieldsTest, ReverseFieldOrder) {
ASSERT_EQ(0x56781234ULL, (unsigned long long)rf2.ReverseFieldOrder(0x12345678));

// Many small fields.
RegisterFlags rf3("", 4,
{make_field(31, 31), make_field(30, 30), make_field(29, 29),
make_field(28, 28)});
RegisterFlags rf3(
"", 4, {make_field(31), make_field(30), make_field(29), make_field(28)});
ASSERT_EQ(0x00000005ULL, rf3.ReverseFieldOrder(0xA0000000));
}

Expand Down Expand Up @@ -167,7 +170,7 @@ TEST(RegisterFlagsTest, AsTable) {
pos_wider.AsTable(100));

// Single bit fields don't need to show start and end, just one of them.
RegisterFlags single_bit("", 4, {make_field(31, 31)});
RegisterFlags single_bit("", 4, {make_field(31)});
ASSERT_EQ("| 31 | 30-0 |\n"
"|----|------|\n"
"| | |",
Expand All @@ -177,7 +180,7 @@ TEST(RegisterFlagsTest, AsTable) {
RegisterFlags many_fields("", 4,
{RegisterFlags::Field("cat", 28, 31),
RegisterFlags::Field("pigeon", 20, 23),
RegisterFlags::Field("wolf", 12, 12),
RegisterFlags::Field("wolf", 12),
RegisterFlags::Field("x", 0, 4)});
ASSERT_EQ("| 31-28 | 27-24 | 23-20 | 19-13 | 12 | 11-5 | 4-0 |\n"
"|-------|-------|--------|-------|------|------|-----|\n"
Expand Down