xref: /llvm-project/lldb/unittests/Target/RegisterFlagsTest.cpp (revision fe929770f41e7b962ebaaeb0a77773a3b03f8b8c)
1 //===-- RegisterFlagsTest.cpp ---------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/Target/RegisterFlags.h"
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
12 
13 using namespace lldb_private;
14 using namespace lldb;
15 
16 TEST(RegisterFlagsTest, Field) {
17   // We assume that start <= end is always true, so that is not tested here.
18 
19   RegisterFlags::Field f1("abc", 0);
20   ASSERT_EQ(f1.GetName(), "abc");
21   // start == end means a 1 bit field.
22   ASSERT_EQ(f1.GetSizeInBits(), (unsigned)1);
23   ASSERT_EQ(f1.GetMask(), (uint64_t)1);
24   ASSERT_EQ(f1.GetValue(0), (uint64_t)0);
25   ASSERT_EQ(f1.GetValue(3), (uint64_t)1);
26 
27   // End is inclusive meaning that start 0 to end 1 includes bit 1
28   // to make a 2 bit field.
29   RegisterFlags::Field f2("", 0, 1);
30   ASSERT_EQ(f2.GetSizeInBits(), (unsigned)2);
31   ASSERT_EQ(f2.GetMask(), (uint64_t)3);
32   ASSERT_EQ(f2.GetValue(UINT64_MAX), (uint64_t)3);
33   ASSERT_EQ(f2.GetValue(UINT64_MAX & ~(uint64_t)3), (uint64_t)0);
34 
35   // If the field doesn't start at 0 we need to shift up/down
36   // to account for it.
37   RegisterFlags::Field f3("", 2, 5);
38   ASSERT_EQ(f3.GetSizeInBits(), (unsigned)4);
39   ASSERT_EQ(f3.GetMask(), (uint64_t)0x3c);
40   ASSERT_EQ(f3.GetValue(UINT64_MAX), (uint64_t)0xf);
41   ASSERT_EQ(f3.GetValue(UINT64_MAX & ~(uint64_t)0x3c), (uint64_t)0);
42 
43   // Fields are sorted lowest starting bit first.
44   ASSERT_TRUE(f2 < f3);
45   ASSERT_FALSE(f3 < f1);
46   ASSERT_FALSE(f1 < f2);
47   ASSERT_FALSE(f1 < f1);
48 }
49 
50 static RegisterFlags::Field make_field(unsigned start, unsigned end) {
51   return RegisterFlags::Field("", start, end);
52 }
53 
54 static RegisterFlags::Field make_field(unsigned bit) {
55   return RegisterFlags::Field("", bit);
56 }
57 
58 TEST(RegisterFlagsTest, FieldOverlaps) {
59   // Single bit fields
60   ASSERT_FALSE(make_field(0, 0).Overlaps(make_field(1)));
61   ASSERT_TRUE(make_field(1, 1).Overlaps(make_field(1)));
62   ASSERT_FALSE(make_field(1, 1).Overlaps(make_field(3)));
63 
64   ASSERT_TRUE(make_field(0, 1).Overlaps(make_field(1, 2)));
65   ASSERT_TRUE(make_field(1, 2).Overlaps(make_field(0, 1)));
66   ASSERT_FALSE(make_field(0, 1).Overlaps(make_field(2, 3)));
67   ASSERT_FALSE(make_field(2, 3).Overlaps(make_field(0, 1)));
68 
69   ASSERT_FALSE(make_field(1, 5).Overlaps(make_field(10, 20)));
70   ASSERT_FALSE(make_field(15, 30).Overlaps(make_field(7, 12)));
71 }
72 
73 TEST(RegisterFlagsTest, PaddingDistance) {
74   // We assume that this method is always called with a more significant
75   // (start bit is higher) field first and that they do not overlap.
76 
77   // [field 1][field 2]
78   ASSERT_EQ(make_field(1, 1).PaddingDistance(make_field(0)), 0ULL);
79   // [field 1][..][field 2]
80   ASSERT_EQ(make_field(2, 2).PaddingDistance(make_field(0)), 1ULL);
81   // [field 1][field 1][field 2]
82   ASSERT_EQ(make_field(1, 2).PaddingDistance(make_field(0)), 0ULL);
83   // [field 1][30 bits free][field 2]
84   ASSERT_EQ(make_field(31, 31).PaddingDistance(make_field(0)), 30ULL);
85 }
86 
87 static void test_padding(const std::vector<RegisterFlags::Field> &fields,
88                          const std::vector<RegisterFlags::Field> &expected) {
89   RegisterFlags rf("", 4, fields);
90   EXPECT_THAT(expected, ::testing::ContainerEq(rf.GetFields()));
91 }
92 
93 TEST(RegisterFlagsTest, RegisterFlagsPadding) {
94   // When creating a set of flags we assume that:
95   // * There are >= 1 fields.
96   // * They are sorted in descending order.
97   // * There may be gaps between each field.
98 
99   // Needs no padding
100   auto fields =
101       std::vector<RegisterFlags::Field>{make_field(16, 31), make_field(0, 15)};
102   test_padding(fields, fields);
103 
104   // Needs padding in between the fields, single bit.
105   test_padding({make_field(17, 31), make_field(0, 15)},
106                {make_field(17, 31), make_field(16), make_field(0, 15)});
107   // Multiple bits of padding.
108   test_padding({make_field(17, 31), make_field(0, 14)},
109                {make_field(17, 31), make_field(15, 16), make_field(0, 14)});
110 
111   // Padding before first field, single bit.
112   test_padding({make_field(0, 30)}, {make_field(31), make_field(0, 30)});
113   // Multiple bits.
114   test_padding({make_field(0, 15)}, {make_field(16, 31), make_field(0, 15)});
115 
116   // Padding after last field, single bit.
117   test_padding({make_field(1, 31)}, {make_field(1, 31), make_field(0)});
118   // Multiple bits.
119   test_padding({make_field(2, 31)}, {make_field(2, 31), make_field(0, 1)});
120 
121   // Fields need padding before, in between and after.
122   // [31-28][field 27-24][23-22][field 21-20][19-12][field 11-8][7-0]
123   test_padding({make_field(24, 27), make_field(20, 21), make_field(8, 11)},
124                {make_field(28, 31), make_field(24, 27), make_field(22, 23),
125                 make_field(20, 21), make_field(12, 19), make_field(8, 11),
126                 make_field(0, 7)});
127 }
128 
129 TEST(RegisterFieldsTest, ReverseFieldOrder) {
130   // Unchanged
131   RegisterFlags rf("", 4, {make_field(0, 31)});
132   ASSERT_EQ(0x12345678ULL, (unsigned long long)rf.ReverseFieldOrder(0x12345678));
133 
134   // Swap the two halves around.
135   RegisterFlags rf2("", 4, {make_field(16, 31), make_field(0, 15)});
136   ASSERT_EQ(0x56781234ULL, (unsigned long long)rf2.ReverseFieldOrder(0x12345678));
137 
138   // Many small fields.
139   RegisterFlags rf3(
140       "", 4, {make_field(31), make_field(30), make_field(29), make_field(28)});
141   ASSERT_EQ(0x00000005ULL, rf3.ReverseFieldOrder(0xA0000000));
142 }
143 
144 TEST(RegisterFlagsTest, AsTable) {
145   // Anonymous fields are shown with an empty name cell,
146   // whether they are known up front or added during construction.
147   RegisterFlags anon_field("", 4, {make_field(0, 31)});
148   ASSERT_EQ("| 31-0 |\n"
149             "|------|\n"
150             "|      |",
151             anon_field.AsTable(100));
152 
153   RegisterFlags anon_with_pad("", 4, {make_field(16, 31)});
154   ASSERT_EQ("| 31-16 | 15-0 |\n"
155             "|-------|------|\n"
156             "|       |      |",
157             anon_with_pad.AsTable(100));
158 
159   // Use the wider of position and name to set the column width.
160   RegisterFlags name_wider("", 4, {RegisterFlags::Field("aardvark", 0, 31)});
161   ASSERT_EQ("|   31-0   |\n"
162             "|----------|\n"
163             "| aardvark |",
164             name_wider.AsTable(100));
165   // When the padding is an odd number, put the remaining 1 on the right.
166   RegisterFlags pos_wider("", 4, {RegisterFlags::Field("?", 0, 31)});
167   ASSERT_EQ("| 31-0 |\n"
168             "|------|\n"
169             "|  ?   |",
170             pos_wider.AsTable(100));
171 
172   // Single bit fields don't need to show start and end, just one of them.
173   RegisterFlags single_bit("", 4, {make_field(31)});
174   ASSERT_EQ("| 31 | 30-0 |\n"
175             "|----|------|\n"
176             "|    |      |",
177             single_bit.AsTable(100));
178 
179   // Columns are printed horizontally if max width allows.
180   RegisterFlags many_fields("", 4,
181                             {RegisterFlags::Field("cat", 28, 31),
182                              RegisterFlags::Field("pigeon", 20, 23),
183                              RegisterFlags::Field("wolf", 12),
184                              RegisterFlags::Field("x", 0, 4)});
185   ASSERT_EQ("| 31-28 | 27-24 | 23-20  | 19-13 |  12  | 11-5 | 4-0 |\n"
186             "|-------|-------|--------|-------|------|------|-----|\n"
187             "|  cat  |       | pigeon |       | wolf |      |  x  |",
188             many_fields.AsTable(100));
189 
190   // max_width tells us when we need to split into further tables.
191   // Here no split is needed.
192   RegisterFlags exact_max_single_col("", 4, {RegisterFlags::Field("?", 0, 31)});
193   ASSERT_EQ("| 31-0 |\n"
194             "|------|\n"
195             "|  ?   |",
196             exact_max_single_col.AsTable(9));
197   RegisterFlags exact_max_two_col(
198       "", 4,
199       {RegisterFlags::Field("?", 16, 31), RegisterFlags::Field("#", 0, 15)});
200   ASSERT_EQ("| 31-16 | 15-0 |\n"
201             "|-------|------|\n"
202             "|   ?   |  #   |",
203             exact_max_two_col.AsTable(16));
204 
205   // If max is less than a single column, just print the single column. The user
206   // will have to put up with some wrapping in this niche case.
207   RegisterFlags zero_max_single_col("", 4, {RegisterFlags::Field("?", 0, 31)});
208   ASSERT_EQ("| 31-0 |\n"
209             "|------|\n"
210             "|  ?   |",
211             zero_max_single_col.AsTable(0));
212   // Same logic for any following columns. Effectively making a "vertical"
213   // table, just with more grid lines.
214   RegisterFlags zero_max_two_col(
215       "", 4,
216       {RegisterFlags::Field("?", 16, 31), RegisterFlags::Field("#", 0, 15)});
217   ASSERT_EQ("| 31-16 |\n"
218             "|-------|\n"
219             "|   ?   |\n"
220             "\n"
221             "| 15-0 |\n"
222             "|------|\n"
223             "|  #   |",
224             zero_max_two_col.AsTable(0));
225 
226   RegisterFlags max_less_than_single_col("", 4,
227                                          {RegisterFlags::Field("?", 0, 31)});
228   ASSERT_EQ("| 31-0 |\n"
229             "|------|\n"
230             "|  ?   |",
231             max_less_than_single_col.AsTable(3));
232   RegisterFlags max_less_than_two_col(
233       "", 4,
234       {RegisterFlags::Field("?", 16, 31), RegisterFlags::Field("#", 0, 15)});
235   ASSERT_EQ("| 31-16 |\n"
236             "|-------|\n"
237             "|   ?   |\n"
238             "\n"
239             "| 15-0 |\n"
240             "|------|\n"
241             "|  #   |",
242             max_less_than_two_col.AsTable(9));
243   RegisterFlags max_many_columns(
244       "", 4,
245       {RegisterFlags::Field("A", 24, 31), RegisterFlags::Field("B", 16, 23),
246        RegisterFlags::Field("C", 8, 15),
247        RegisterFlags::Field("really long name", 0, 7)});
248   ASSERT_EQ("| 31-24 | 23-16 |\n"
249             "|-------|-------|\n"
250             "|   A   |   B   |\n"
251             "\n"
252             "| 15-8 |\n"
253             "|------|\n"
254             "|  C   |\n"
255             "\n"
256             "|       7-0        |\n"
257             "|------------------|\n"
258             "| really long name |",
259             max_many_columns.AsTable(23));
260 }
261