xref: /llvm-project/lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp (revision ee1adc5aab4fb517314358ce03cfda426da9c4ce)
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;
102     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_begin, 3, op_lit_uint, 42,
103                            op_return, op_if, op_lit_uint, 23},
104                           data));
105     ASSERT_EQ(data.Pop<uint64_t>(), 42u);
106   }
107 }
108 
109 TEST_F(FormatterBytecodeTest, ConversionOps) {
110   {
111     DataStack data(lldb::ValueObjectSP{});
112     ASSERT_TRUE(Interpret({op_is_null}, data));
113     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
114   }
115   {
116     DataStack data;
117     ASSERT_TRUE(Interpret({op_lit_uint, 1u, op_as_int}, data));
118     ASSERT_EQ(data.Pop<int64_t>(), 1);
119   }
120   {
121     DataStack data;
122     ASSERT_TRUE(Interpret({op_lit_int, 126, op_as_uint}, data));
123     ASSERT_EQ(data.Pop<uint64_t>(), ~1ULL);
124   }
125 }
126 
127 TEST_F(FormatterBytecodeTest, ArithOps) {
128   {
129     DataStack data;
130     ASSERT_TRUE(Interpret({op_lit_uint, 2, op_lit_uint, 3, op_plus}, data));
131     ASSERT_EQ(data.Pop<uint64_t>(), 5u);
132   }
133   {
134     DataStack data;
135     ASSERT_TRUE(Interpret({op_lit_uint, 3, op_lit_uint, 2, op_minus}, data));
136     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
137   }
138   {
139     DataStack data;
140     ASSERT_TRUE(Interpret({op_lit_uint, 3, op_lit_uint, 2, op_mul}, data));
141     ASSERT_EQ(data.Pop<uint64_t>(), 6u);
142   }
143   {
144     DataStack data;
145     ASSERT_TRUE(Interpret({op_lit_uint, 6, op_lit_uint, 2, op_div}, data));
146     ASSERT_EQ(data.Pop<uint64_t>(), 3u);
147   }
148   {
149     DataStack data;
150     ASSERT_FALSE(Interpret({op_lit_uint, 23, op_lit_uint, 0, op_div}, data));
151   }
152   {
153     DataStack data;
154     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 2, op_shl}, data));
155     ASSERT_EQ(data.Pop<uint64_t>(), 4u);
156   }
157   {
158     DataStack data;
159     unsigned char minus_one = 127;
160     ASSERT_FALSE(
161         Interpret({op_lit_int, minus_one, op_lit_uint, 2, op_shl}, data));
162     unsigned char minus_two = 126;
163     ASSERT_TRUE(
164         Interpret({op_lit_int, minus_two, op_lit_uint, 1, op_shr}, data));
165     ASSERT_EQ(data.Pop<int64_t>(), -1);
166   }
167   {
168     DataStack data;
169     ASSERT_FALSE(Interpret({op_lit_uint, 1, op_lit_uint, 65, op_shl}, data));
170     ASSERT_FALSE(Interpret({op_lit_uint, 1, op_lit_uint, 65, op_shr}, data));
171   }
172   {
173     DataStack data;
174     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_and}, data));
175     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
176     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_and}, data));
177     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
178   }
179   {
180     DataStack data;
181     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_or}, data));
182     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
183     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_or}, data));
184     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
185     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_or}, data));
186     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
187   }
188   {
189     DataStack data;
190     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_xor}, data));
191     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
192     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_xor}, data));
193     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
194     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_xor}, data));
195     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
196   }
197   {
198     DataStack data;
199     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_not}, data));
200     ASSERT_EQ(data.Pop<uint64_t>(), 0xffffffffffffffff);
201   }
202   {
203     DataStack data;
204     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_eq}, data));
205     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
206     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_eq}, data));
207     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
208   }
209   {
210     DataStack data;
211     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_neq}, data));
212     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
213     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_neq}, data));
214     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
215   }
216   {
217     DataStack data;
218     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_lt}, data));
219     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
220     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_lt}, data));
221     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
222     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_lt}, data));
223     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
224   }
225   {
226     DataStack data;
227     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_gt}, data));
228     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
229     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_gt}, data));
230     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
231     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_gt}, data));
232     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
233   }
234   {
235     DataStack data;
236     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_le}, data));
237     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
238     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_le}, data));
239     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
240     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_le}, data));
241     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
242   }
243   {
244     DataStack data;
245     ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_ge}, data));
246     ASSERT_EQ(data.Pop<uint64_t>(), 0u);
247     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_ge}, data));
248     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
249     ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_ge}, data));
250     ASSERT_EQ(data.Pop<uint64_t>(), 1u);
251   }
252 }
253 
254 TEST_F(FormatterBytecodeTest, CallOps) {
255   {
256     DataStack data;
257     data.Push(std::string{"hello"});
258     ASSERT_TRUE(Interpret({op_lit_selector, sel_strlen, op_call}, data));
259     ASSERT_EQ(data.Pop<uint64_t>(), 5u);
260   }
261   {
262     DataStack data;
263     data.Push(std::string{"A"});
264     data.Push(std::string{"B"});
265     data.Push(std::string{"{1}{0}"});
266     ASSERT_TRUE(Interpret({op_lit_selector, sel_fmt, op_call}, data));
267     ASSERT_EQ(data.Pop<std::string>(), "BA");
268   }
269   {
270     DataStack data;
271     data.Push(std::string{"{0}"});
272     ASSERT_FALSE(Interpret({op_lit_selector, sel_fmt, op_call}, data));
273   }
274 }
275