1 //===-- RegisterFlagsTest.cpp ---------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Target/RegisterFlags.h"
10 #include "lldb/Utility/StreamString.h"
11 #include "gmock/gmock.h"
12 #include "gtest/gtest.h"
14 using namespace lldb_private
;
17 TEST(RegisterFlagsTest
, Field
) {
18 // We assume that start <= end is always true, so that is not tested here.
20 RegisterFlags::Field
f1("abc", 0);
21 ASSERT_EQ(f1
.GetName(), "abc");
22 // start == end means a 1 bit field.
23 ASSERT_EQ(f1
.GetSizeInBits(), (unsigned)1);
24 ASSERT_EQ(f1
.GetMask(), (uint64_t)1);
25 ASSERT_EQ(f1
.GetValue(0), (uint64_t)0);
26 ASSERT_EQ(f1
.GetValue(3), (uint64_t)1);
28 // End is inclusive meaning that start 0 to end 1 includes bit 1
29 // to make a 2 bit field.
30 RegisterFlags::Field
f2("", 0, 1);
31 ASSERT_EQ(f2
.GetSizeInBits(), (unsigned)2);
32 ASSERT_EQ(f2
.GetMask(), (uint64_t)3);
33 ASSERT_EQ(f2
.GetValue(UINT64_MAX
), (uint64_t)3);
34 ASSERT_EQ(f2
.GetValue(UINT64_MAX
& ~(uint64_t)3), (uint64_t)0);
36 // If the field doesn't start at 0 we need to shift up/down
38 RegisterFlags::Field
f3("", 2, 5);
39 ASSERT_EQ(f3
.GetSizeInBits(), (unsigned)4);
40 ASSERT_EQ(f3
.GetMask(), (uint64_t)0x3c);
41 ASSERT_EQ(f3
.GetValue(UINT64_MAX
), (uint64_t)0xf);
42 ASSERT_EQ(f3
.GetValue(UINT64_MAX
& ~(uint64_t)0x3c), (uint64_t)0);
44 // Fields are sorted lowest starting bit first.
46 ASSERT_FALSE(f3
< f1
);
47 ASSERT_FALSE(f1
< f2
);
48 ASSERT_FALSE(f1
< f1
);
51 static RegisterFlags::Field
make_field(unsigned start
, unsigned end
) {
52 return RegisterFlags::Field("", start
, end
);
55 static RegisterFlags::Field
make_field(unsigned bit
) {
56 return RegisterFlags::Field("", bit
);
59 TEST(RegisterFlagsTest
, FieldOverlaps
) {
61 ASSERT_FALSE(make_field(0, 0).Overlaps(make_field(1)));
62 ASSERT_TRUE(make_field(1, 1).Overlaps(make_field(1)));
63 ASSERT_FALSE(make_field(1, 1).Overlaps(make_field(3)));
65 ASSERT_TRUE(make_field(0, 1).Overlaps(make_field(1, 2)));
66 ASSERT_TRUE(make_field(1, 2).Overlaps(make_field(0, 1)));
67 ASSERT_FALSE(make_field(0, 1).Overlaps(make_field(2, 3)));
68 ASSERT_FALSE(make_field(2, 3).Overlaps(make_field(0, 1)));
70 ASSERT_FALSE(make_field(1, 5).Overlaps(make_field(10, 20)));
71 ASSERT_FALSE(make_field(15, 30).Overlaps(make_field(7, 12)));
74 TEST(RegisterFlagsTest
, PaddingDistance
) {
75 // We assume that this method is always called with a more significant
76 // (start bit is higher) field first and that they do not overlap.
79 ASSERT_EQ(make_field(1, 1).PaddingDistance(make_field(0)), 0ULL);
80 // [field 1][..][field 2]
81 ASSERT_EQ(make_field(2, 2).PaddingDistance(make_field(0)), 1ULL);
82 // [field 1][field 1][field 2]
83 ASSERT_EQ(make_field(1, 2).PaddingDistance(make_field(0)), 0ULL);
84 // [field 1][30 bits free][field 2]
85 ASSERT_EQ(make_field(31, 31).PaddingDistance(make_field(0)), 30ULL);
88 static void test_padding(const std::vector
<RegisterFlags::Field
> &fields
,
89 const std::vector
<RegisterFlags::Field
> &expected
) {
90 RegisterFlags
rf("", 4, fields
);
91 EXPECT_THAT(expected
, ::testing::ContainerEq(rf
.GetFields()));
94 TEST(RegisterFlagsTest
, RegisterFlagsPadding
) {
95 // When creating a set of flags we assume that:
96 // * There are >= 1 fields.
97 // * They are sorted in descending order.
98 // * There may be gaps between each field.
102 std::vector
<RegisterFlags::Field
>{make_field(16, 31), make_field(0, 15)};
103 test_padding(fields
, fields
);
105 // Needs padding in between the fields, single bit.
106 test_padding({make_field(17, 31), make_field(0, 15)},
107 {make_field(17, 31), make_field(16), make_field(0, 15)});
108 // Multiple bits of padding.
109 test_padding({make_field(17, 31), make_field(0, 14)},
110 {make_field(17, 31), make_field(15, 16), make_field(0, 14)});
112 // Padding before first field, single bit.
113 test_padding({make_field(0, 30)}, {make_field(31), make_field(0, 30)});
115 test_padding({make_field(0, 15)}, {make_field(16, 31), make_field(0, 15)});
117 // Padding after last field, single bit.
118 test_padding({make_field(1, 31)}, {make_field(1, 31), make_field(0)});
120 test_padding({make_field(2, 31)}, {make_field(2, 31), make_field(0, 1)});
122 // Fields need padding before, in between and after.
123 // [31-28][field 27-24][23-22][field 21-20][19-12][field 11-8][7-0]
124 test_padding({make_field(24, 27), make_field(20, 21), make_field(8, 11)},
125 {make_field(28, 31), make_field(24, 27), make_field(22, 23),
126 make_field(20, 21), make_field(12, 19), make_field(8, 11),
130 TEST(RegisterFieldsTest
, ReverseFieldOrder
) {
132 RegisterFlags
rf("", 4, {make_field(0, 31)});
133 ASSERT_EQ(0x12345678ULL
, (unsigned long long)rf
.ReverseFieldOrder(0x12345678));
135 // Swap the two halves around.
136 RegisterFlags
rf2("", 4, {make_field(16, 31), make_field(0, 15)});
137 ASSERT_EQ(0x56781234ULL
, (unsigned long long)rf2
.ReverseFieldOrder(0x12345678));
139 // Many small fields.
141 "", 4, {make_field(31), make_field(30), make_field(29), make_field(28)});
142 ASSERT_EQ(0x00000005ULL
, rf3
.ReverseFieldOrder(0xA0000000));
145 TEST(RegisterFlagsTest
, AsTable
) {
146 // Anonymous fields are shown with an empty name cell,
147 // whether they are known up front or added during construction.
148 RegisterFlags
anon_field("", 4, {make_field(0, 31)});
149 ASSERT_EQ("| 31-0 |\n"
152 anon_field
.AsTable(100));
154 RegisterFlags
anon_with_pad("", 4, {make_field(16, 31)});
155 ASSERT_EQ("| 31-16 | 15-0 |\n"
158 anon_with_pad
.AsTable(100));
160 // Use the wider of position and name to set the column width.
161 RegisterFlags
name_wider("", 4, {RegisterFlags::Field("aardvark", 0, 31)});
162 ASSERT_EQ("| 31-0 |\n"
165 name_wider
.AsTable(100));
166 // When the padding is an odd number, put the remaining 1 on the right.
167 RegisterFlags
pos_wider("", 4, {RegisterFlags::Field("?", 0, 31)});
168 ASSERT_EQ("| 31-0 |\n"
171 pos_wider
.AsTable(100));
173 // Single bit fields don't need to show start and end, just one of them.
174 RegisterFlags
single_bit("", 4, {make_field(31)});
175 ASSERT_EQ("| 31 | 30-0 |\n"
178 single_bit
.AsTable(100));
180 // Columns are printed horizontally if max width allows.
181 RegisterFlags
many_fields("", 4,
182 {RegisterFlags::Field("cat", 28, 31),
183 RegisterFlags::Field("pigeon", 20, 23),
184 RegisterFlags::Field("wolf", 12),
185 RegisterFlags::Field("x", 0, 4)});
186 ASSERT_EQ("| 31-28 | 27-24 | 23-20 | 19-13 | 12 | 11-5 | 4-0 |\n"
187 "|-------|-------|--------|-------|------|------|-----|\n"
188 "| cat | | pigeon | | wolf | | x |",
189 many_fields
.AsTable(100));
191 // max_width tells us when we need to split into further tables.
192 // Here no split is needed.
193 RegisterFlags
exact_max_single_col("", 4, {RegisterFlags::Field("?", 0, 31)});
194 ASSERT_EQ("| 31-0 |\n"
197 exact_max_single_col
.AsTable(9));
198 RegisterFlags
exact_max_two_col(
200 {RegisterFlags::Field("?", 16, 31), RegisterFlags::Field("#", 0, 15)});
201 ASSERT_EQ("| 31-16 | 15-0 |\n"
204 exact_max_two_col
.AsTable(16));
206 // If max is less than a single column, just print the single column. The user
207 // will have to put up with some wrapping in this niche case.
208 RegisterFlags
zero_max_single_col("", 4, {RegisterFlags::Field("?", 0, 31)});
209 ASSERT_EQ("| 31-0 |\n"
212 zero_max_single_col
.AsTable(0));
213 // Same logic for any following columns. Effectively making a "vertical"
214 // table, just with more grid lines.
215 RegisterFlags
zero_max_two_col(
217 {RegisterFlags::Field("?", 16, 31), RegisterFlags::Field("#", 0, 15)});
218 ASSERT_EQ("| 31-16 |\n"
225 zero_max_two_col
.AsTable(0));
227 RegisterFlags
max_less_than_single_col("", 4,
228 {RegisterFlags::Field("?", 0, 31)});
229 ASSERT_EQ("| 31-0 |\n"
232 max_less_than_single_col
.AsTable(3));
233 RegisterFlags
max_less_than_two_col(
235 {RegisterFlags::Field("?", 16, 31), RegisterFlags::Field("#", 0, 15)});
236 ASSERT_EQ("| 31-16 |\n"
243 max_less_than_two_col
.AsTable(9));
244 RegisterFlags
max_many_columns(
246 {RegisterFlags::Field("A", 24, 31), RegisterFlags::Field("B", 16, 23),
247 RegisterFlags::Field("C", 8, 15),
248 RegisterFlags::Field("really long name", 0, 7)});
249 ASSERT_EQ("| 31-24 | 23-16 |\n"
250 "|-------|-------|\n"
258 "|------------------|\n"
259 "| really long name |",
260 max_many_columns
.AsTable(23));
263 TEST(RegisterFieldsTest
, ToXML
) {
266 // RegisterFlags requires that some fields be given, so no testing of empty
269 // Unnamed fields are padding that are ignored. This applies to fields passed
270 // in, and those generated to fill the other bits (31-1 here).
271 RegisterFlags("Foo", 4, {RegisterFlags::Field("", 0, 0)}).ToXML(strm
);
272 ASSERT_EQ(strm
.GetString(), "<flags id=\"Foo\" size=\"4\">\n"
276 RegisterFlags("Foo", 4, {RegisterFlags::Field("abc", 0, 0)}).ToXML(strm
);
277 ASSERT_EQ(strm
.GetString(), "<flags id=\"Foo\" size=\"4\">\n"
278 " <field name=\"abc\" start=\"0\" end=\"0\"/>\n"
282 // Should use the current indentation level as a starting point.
286 {RegisterFlags::Field("f1", 25, 32), RegisterFlags::Field("f2", 10, 24)})
288 ASSERT_EQ(strm
.GetString(),
289 " <flags id=\"Bar\" size=\"5\">\n"
290 " <field name=\"f1\" start=\"25\" end=\"32\"/>\n"
291 " <field name=\"f2\" start=\"10\" end=\"24\"/>\n"
296 // Should replace any XML unsafe characters in field names.
297 RegisterFlags("Safe", 8,
298 {RegisterFlags::Field("A<", 4), RegisterFlags::Field("B>", 3),
299 RegisterFlags::Field("C'", 2), RegisterFlags::Field("D\"", 1),
300 RegisterFlags::Field("E&", 0)})
302 ASSERT_EQ(strm
.GetString(),
303 "<flags id=\"Safe\" size=\"8\">\n"
304 " <field name=\"A<\" start=\"4\" end=\"4\"/>\n"
305 " <field name=\"B>\" start=\"3\" end=\"3\"/>\n"
306 " <field name=\"C'\" start=\"2\" end=\"2\"/>\n"
307 " <field name=\"D"\" start=\"1\" end=\"1\"/>\n"
308 " <field name=\"E&\" start=\"0\" end=\"0\"/>\n"