1 | //===- MachineInstrBundleIteratorTest.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 "llvm/CodeGen/MachineInstrBundleIterator.h" |
10 | #include "llvm/ADT/ilist_node.h" |
11 | #include "gtest/gtest.h" |
12 | |
13 | using namespace llvm; |
14 | |
15 | namespace { |
16 | |
17 | struct MyBundledInstr |
18 | : public ilist_node<MyBundledInstr, ilist_sentinel_tracking<true>> { |
19 | bool isBundledWithPred() const { return true; } |
20 | bool isBundledWithSucc() const { return true; } |
21 | }; |
22 | typedef MachineInstrBundleIterator<MyBundledInstr> bundled_iterator; |
23 | typedef MachineInstrBundleIterator<const MyBundledInstr> const_bundled_iterator; |
24 | typedef MachineInstrBundleIterator<MyBundledInstr, true> |
25 | reverse_bundled_iterator; |
26 | typedef MachineInstrBundleIterator<const MyBundledInstr, true> |
27 | const_reverse_bundled_iterator; |
28 | |
29 | #ifdef GTEST_HAS_DEATH_TEST |
30 | #ifndef NDEBUG |
31 | TEST(MachineInstrBundleIteratorTest, CheckForBundles) { |
32 | MyBundledInstr MBI; |
33 | auto I = MBI.getIterator(); |
34 | auto RI = I.getReverse(); |
35 | |
36 | // Confirm that MBI is always considered bundled. |
37 | EXPECT_TRUE(MBI.isBundledWithPred()); |
38 | EXPECT_TRUE(MBI.isBundledWithSucc()); |
39 | |
40 | // Confirm that iterators check in their constructor for bundled iterators. |
41 | EXPECT_DEATH((void)static_cast<bundled_iterator>(I), |
42 | "not legal to initialize" ); |
43 | EXPECT_DEATH((void)static_cast<bundled_iterator>(MBI), |
44 | "not legal to initialize" ); |
45 | EXPECT_DEATH((void)static_cast<bundled_iterator>(&MBI), |
46 | "not legal to initialize" ); |
47 | EXPECT_DEATH((void)static_cast<const_bundled_iterator>(I), |
48 | "not legal to initialize" ); |
49 | EXPECT_DEATH((void)static_cast<const_bundled_iterator>(MBI), |
50 | "not legal to initialize" ); |
51 | EXPECT_DEATH((void)static_cast<const_bundled_iterator>(&MBI), |
52 | "not legal to initialize" ); |
53 | EXPECT_DEATH((void)static_cast<reverse_bundled_iterator>(RI), |
54 | "not legal to initialize" ); |
55 | EXPECT_DEATH((void)static_cast<reverse_bundled_iterator>(MBI), |
56 | "not legal to initialize" ); |
57 | EXPECT_DEATH((void)static_cast<reverse_bundled_iterator>(&MBI), |
58 | "not legal to initialize" ); |
59 | EXPECT_DEATH((void)static_cast<const_reverse_bundled_iterator>(RI), |
60 | "not legal to initialize" ); |
61 | EXPECT_DEATH((void)static_cast<const_reverse_bundled_iterator>(MBI), |
62 | "not legal to initialize" ); |
63 | EXPECT_DEATH((void)static_cast<const_reverse_bundled_iterator>(&MBI), |
64 | "not legal to initialize" ); |
65 | } |
66 | #endif |
67 | #endif |
68 | |
69 | TEST(MachineInstrBundleIteratorTest, CompareToBundledMI) { |
70 | MyBundledInstr MBI; |
71 | const MyBundledInstr &CMBI = MBI; |
72 | bundled_iterator I; |
73 | const_bundled_iterator CI; |
74 | |
75 | // Confirm that MBI is always considered bundled. |
76 | EXPECT_TRUE(MBI.isBundledWithPred()); |
77 | EXPECT_TRUE(MBI.isBundledWithSucc()); |
78 | |
79 | // These invocations will crash when !NDEBUG if a conversion is taking place. |
80 | // These checks confirm that comparison operators don't use any conversion |
81 | // operators. |
82 | ASSERT_FALSE(MBI == I); |
83 | ASSERT_FALSE(&MBI == I); |
84 | ASSERT_FALSE(CMBI == I); |
85 | ASSERT_FALSE(&CMBI == I); |
86 | ASSERT_FALSE(I == MBI); |
87 | ASSERT_FALSE(I == &MBI); |
88 | ASSERT_FALSE(I == CMBI); |
89 | ASSERT_FALSE(I == &CMBI); |
90 | ASSERT_FALSE(MBI == CI); |
91 | ASSERT_FALSE(&MBI == CI); |
92 | ASSERT_FALSE(CMBI == CI); |
93 | ASSERT_FALSE(&CMBI == CI); |
94 | ASSERT_FALSE(CI == MBI); |
95 | ASSERT_FALSE(CI == &MBI); |
96 | ASSERT_FALSE(CI == CMBI); |
97 | ASSERT_FALSE(CI == &CMBI); |
98 | ASSERT_FALSE(MBI.getIterator() == I); |
99 | ASSERT_FALSE(CMBI.getIterator() == I); |
100 | ASSERT_FALSE(I == MBI.getIterator()); |
101 | ASSERT_FALSE(I == CMBI.getIterator()); |
102 | ASSERT_FALSE(MBI.getIterator() == CI); |
103 | ASSERT_FALSE(CMBI.getIterator() == CI); |
104 | ASSERT_FALSE(CI == MBI.getIterator()); |
105 | ASSERT_FALSE(CI == CMBI.getIterator()); |
106 | ASSERT_TRUE(MBI != I); |
107 | ASSERT_TRUE(&MBI != I); |
108 | ASSERT_TRUE(CMBI != I); |
109 | ASSERT_TRUE(&CMBI != I); |
110 | ASSERT_TRUE(I != MBI); |
111 | ASSERT_TRUE(I != &MBI); |
112 | ASSERT_TRUE(I != CMBI); |
113 | ASSERT_TRUE(I != &CMBI); |
114 | ASSERT_TRUE(MBI != CI); |
115 | ASSERT_TRUE(&MBI != CI); |
116 | ASSERT_TRUE(CMBI != CI); |
117 | ASSERT_TRUE(&CMBI != CI); |
118 | ASSERT_TRUE(CI != MBI); |
119 | ASSERT_TRUE(CI != &MBI); |
120 | ASSERT_TRUE(CI != CMBI); |
121 | ASSERT_TRUE(CI != &CMBI); |
122 | ASSERT_TRUE(MBI.getIterator() != I); |
123 | ASSERT_TRUE(CMBI.getIterator() != I); |
124 | ASSERT_TRUE(I != MBI.getIterator()); |
125 | ASSERT_TRUE(I != CMBI.getIterator()); |
126 | ASSERT_TRUE(MBI.getIterator() != CI); |
127 | ASSERT_TRUE(CMBI.getIterator() != CI); |
128 | ASSERT_TRUE(CI != MBI.getIterator()); |
129 | ASSERT_TRUE(CI != CMBI.getIterator()); |
130 | } |
131 | |
132 | struct MyUnbundledInstr |
133 | : ilist_node<MyUnbundledInstr, ilist_sentinel_tracking<true>> { |
134 | bool isBundledWithPred() const { return false; } |
135 | bool isBundledWithSucc() const { return false; } |
136 | }; |
137 | typedef MachineInstrBundleIterator<MyUnbundledInstr> unbundled_iterator; |
138 | typedef MachineInstrBundleIterator<const MyUnbundledInstr> |
139 | const_unbundled_iterator; |
140 | typedef MachineInstrBundleIterator<MyUnbundledInstr, true> |
141 | reverse_unbundled_iterator; |
142 | typedef MachineInstrBundleIterator<const MyUnbundledInstr, true> |
143 | const_reverse_unbundled_iterator; |
144 | |
145 | TEST(MachineInstrBundleIteratorTest, ReverseConstructor) { |
146 | simple_ilist<MyUnbundledInstr, ilist_sentinel_tracking<true>> L; |
147 | const auto &CL = L; |
148 | MyUnbundledInstr A, B; |
149 | L.insert(I: L.end(), Node&: A); |
150 | L.insert(I: L.end(), Node&: B); |
151 | |
152 | // Save typing. |
153 | typedef MachineInstrBundleIterator<MyUnbundledInstr> iterator; |
154 | typedef MachineInstrBundleIterator<MyUnbundledInstr, true> reverse_iterator; |
155 | typedef MachineInstrBundleIterator<const MyUnbundledInstr> const_iterator; |
156 | typedef MachineInstrBundleIterator<const MyUnbundledInstr, true> |
157 | const_reverse_iterator; |
158 | |
159 | // Convert to bundle iterators. |
160 | auto begin = [&]() -> iterator { return L.begin(); }; |
161 | auto end = [&]() -> iterator { return L.end(); }; |
162 | auto rbegin = [&]() -> reverse_iterator { return L.rbegin(); }; |
163 | auto rend = [&]() -> reverse_iterator { return L.rend(); }; |
164 | auto cbegin = [&]() -> const_iterator { return CL.begin(); }; |
165 | auto cend = [&]() -> const_iterator { return CL.end(); }; |
166 | auto crbegin = [&]() -> const_reverse_iterator { return CL.rbegin(); }; |
167 | auto crend = [&]() -> const_reverse_iterator { return CL.rend(); }; |
168 | |
169 | // Check conversion values. |
170 | EXPECT_EQ(begin(), iterator(rend())); |
171 | EXPECT_EQ(++begin(), iterator(++rbegin())); |
172 | EXPECT_EQ(end(), iterator(rbegin())); |
173 | EXPECT_EQ(rbegin(), reverse_iterator(end())); |
174 | EXPECT_EQ(++rbegin(), reverse_iterator(++begin())); |
175 | EXPECT_EQ(rend(), reverse_iterator(begin())); |
176 | |
177 | // Check const iterator constructors. |
178 | EXPECT_EQ(cbegin(), const_iterator(rend())); |
179 | EXPECT_EQ(cbegin(), const_iterator(crend())); |
180 | EXPECT_EQ(crbegin(), const_reverse_iterator(end())); |
181 | EXPECT_EQ(crbegin(), const_reverse_iterator(cend())); |
182 | |
183 | // Confirm lack of implicit conversions. |
184 | static_assert(!std::is_convertible_v<iterator, reverse_iterator>, |
185 | "unexpected implicit conversion" ); |
186 | static_assert(!std::is_convertible_v<reverse_iterator, iterator>, |
187 | "unexpected implicit conversion" ); |
188 | static_assert(!std::is_convertible_v<const_iterator, const_reverse_iterator>, |
189 | "unexpected implicit conversion" ); |
190 | static_assert(!std::is_convertible_v<const_reverse_iterator, const_iterator>, |
191 | "unexpected implicit conversion" ); |
192 | } |
193 | |
194 | } // end namespace |
195 | |