xref: /llvm-project/lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp (revision 9a9c1d4a6155a96ce9be494cec7e25731d36b33e)
1 #include "DataFormatters/FormatterBytecode.h"
2 #include "lldb/Utility/StreamString.h"
3 
4 #include "gtest/gtest.h"
5 
6 using namespace lldb_private;
7 using namespace lldb;
8 using namespace FormatterBytecode;
9 using llvm::StringRef;
10 
11 namespace {
12 class FormatterBytecodeTest : public ::testing::Test {};
13 
14 bool Interpret(std::vector<uint8_t> code, DataStack &data) {
15   auto buf =
16       StringRef(reinterpret_cast<const char *>(code.data()), code.size());
17   std::vector<ControlStackElement> control({buf});
18   if (auto error = Interpret(control, data, sel_summary)) {
19 #ifndef NDEBUG
20     llvm::errs() << llvm::toString(std::move(error)) << '\n';
21 #else
22     llvm::consumeError(std::move(error));
23 #endif
24     return false;
25   }
26   return true;
27 }
28 
29 } // namespace
30 
31 TEST_F(FormatterBytecodeTest, StackOps) {
32   {
33     DataStack data;
34     ASSERT_TRUE(Interpret({op_lit_uint, 23, op_dup, op_plus}, data));
35     ASSERT_EQ(data.Pop<uint64_t>(), 46u);
36   }
37   {
38     DataStack data;
39     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_drop}, data));
40     ASSERT_EQ(data.size(), 0u);
41   }
42   {
43     for (unsigned char i = 0; i < 3; ++i) {
44       DataStack data;
45 
46       ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_lit_uint, 2,
47                              op_lit_uint, i, op_pick},
48                             data));
49       ASSERT_EQ(data.Pop<uint64_t>(), i);
50     }
51   }
52   {
53     DataStack data;
54     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_over}, data));
55     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
56   }
57   {
58     DataStack data;
59     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_swap}, data));
60     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
61     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
62   }
63   {
64     DataStack data;
65     ASSERT_TRUE(Interpret(
66         {op_lit_uint, 0, op_lit_uint, 1, op_lit_uint, 2, op_rot}, data));
67     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
68     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
69     ASSERT_EQ(data.Pop<uint64_t>(), 2u);
70   }
71 }
72 
73 TEST_F(FormatterBytecodeTest, ControlOps) {
74   {
75     DataStack data;
76     ASSERT_TRUE(
77         Interpret({op_lit_uint, 0, op_begin, 2, op_lit_uint, 42, op_if}, data));
78     ASSERT_EQ(data.size(), 0u);
79   }
80   {
81     DataStack data;
82     ASSERT_TRUE(
83         Interpret({op_lit_uint, 1, op_begin, 2, op_lit_uint, 42, op_if}, data));
84     ASSERT_EQ(data.Pop<uint64_t>(), 42u);
85   }
86   {
87     DataStack data;
88     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_begin, 2, op_lit_uint, 42,
89                            op_begin, 2, op_lit_uint, 23, op_ifelse},
90                           data));
91     ASSERT_EQ(data.Pop<uint64_t>(), 23u);
92   }
93   {
94     DataStack data;
95     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_begin, 2, op_lit_uint, 42,
96                            op_begin, 2, op_lit_uint, 23, op_ifelse},
97                           data));
98     ASSERT_EQ(data.Pop<uint64_t>(), 42u);
99   }
100   {
101     DataStack data(lldb::ValueObjectSP{});
102     ASSERT_TRUE(Interpret({op_is_null}, data));
103     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
104   }
105   {
106     DataStack data;
107     ASSERT_TRUE(Interpret({op_lit_uint, 1u, op_as_int}, data));
108     ASSERT_EQ(data.Pop<int64_t>(), 1);
109   }
110   {
111     DataStack data;
112     ASSERT_TRUE(Interpret({op_lit_int, 126, op_as_uint}, data));
113     ASSERT_EQ(data.Pop<uint64_t>(), ~1ULL);
114   }
115 }
116 
117 TEST_F(FormatterBytecodeTest, ArithOps) {
118   {
119     DataStack data;
120     ASSERT_TRUE(Interpret({op_lit_uint, 2, op_lit_uint, 3, op_plus}, data));
121     ASSERT_EQ(data.Pop<uint64_t>(), 5u);
122   }
123   {
124     DataStack data;
125     ASSERT_TRUE(Interpret({op_lit_uint, 3, op_lit_uint, 2, op_minus}, data));
126     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
127   }
128   {
129     DataStack data;
130     ASSERT_TRUE(Interpret({op_lit_uint, 3, op_lit_uint, 2, op_mul}, data));
131     ASSERT_EQ(data.Pop<uint64_t>(), 6u);
132   }
133   {
134     DataStack data;
135     ASSERT_TRUE(Interpret({op_lit_uint, 6, op_lit_uint, 2, op_div}, data));
136     ASSERT_EQ(data.Pop<uint64_t>(), 3u);
137   }
138   {
139     DataStack data;
140     ASSERT_FALSE(Interpret({op_lit_uint, 23, op_lit_uint, 0, op_div}, data));
141   }
142   {
143     DataStack data;
144     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 2, op_shl}, data));
145     ASSERT_EQ(data.Pop<uint64_t>(), 4u);
146   }
147   {
148     DataStack data;
149     unsigned char minus_one = 127;
150     ASSERT_TRUE(
151         Interpret({op_lit_int, minus_one, op_lit_uint, 2, op_shl}, data));
152     ASSERT_EQ(data.Pop<int64_t>(), -4);
153   }
154   {
155     DataStack data;
156     ASSERT_FALSE(Interpret({op_lit_uint, 1, op_lit_uint, 65, op_shl}, data));
157     ASSERT_FALSE(Interpret({op_lit_uint, 1, op_lit_uint, 65, op_shr}, data));
158   }
159   {
160     DataStack data;
161     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_and}, data));
162     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
163     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_and}, data));
164     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
165   }
166   {
167     DataStack data;
168     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_or}, data));
169     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
170     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_or}, data));
171     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
172     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_or}, data));
173     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
174   }
175   {
176     DataStack data;
177     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_xor}, data));
178     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
179     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_xor}, data));
180     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
181     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_xor}, data));
182     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
183   }
184   {
185     DataStack data;
186     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_not}, data));
187     ASSERT_EQ(data.Pop<uint64_t>(), 0xffffffffffffffff);
188   }
189   {
190     DataStack data;
191     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_eq}, data));
192     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
193     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_eq}, data));
194     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
195   }
196   {
197     DataStack data;
198     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_neq}, data));
199     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
200     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_neq}, data));
201     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
202   }
203   {
204     DataStack data;
205     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_lt}, data));
206     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
207     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_lt}, data));
208     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
209     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_lt}, data));
210     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
211   }
212   {
213     DataStack data;
214     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_gt}, data));
215     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
216     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_gt}, data));
217     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
218     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_gt}, data));
219     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
220   }
221   {
222     DataStack data;
223     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_le}, data));
224     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
225     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_le}, data));
226     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
227     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_le}, data));
228     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
229   }
230   {
231     DataStack data;
232     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_ge}, data));
233     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
234     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_ge}, data));
235     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
236     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_ge}, data));
237     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
238   }
239 }
240 
241 TEST_F(FormatterBytecodeTest, CallOps) {
242   {
243     DataStack data;
244     data.Push(std::string{"hello"});
245     ASSERT_TRUE(Interpret({op_lit_selector, sel_strlen, op_call}, data));
246     ASSERT_EQ(data.Pop<uint64_t>(), 5u);
247   }
248   {
249     DataStack data;
250     data.Push(std::string{"A"});
251     data.Push(std::string{"B"});
252     data.Push(std::string{"{1}{0}"});
253     ASSERT_TRUE(Interpret({op_lit_selector, sel_fmt, op_call}, data));
254     ASSERT_EQ(data.Pop<std::string>(), "BA");
255   }
256   {
257     DataStack data;
258     data.Push(std::string{"{0}"});
259     ASSERT_FALSE(Interpret({op_lit_selector, sel_fmt, op_call}, data));
260   }
261 }
262