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