OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 the V8 project authors. All rights reserved. | |
ahaas
2016/05/24 14:48:27
2016
titzer
2016/05/24 15:09:52
Done.
| |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "test/unittests/test-utils.h" | |
6 #include "testing/gmock/include/gmock/gmock.h" | |
7 | |
8 #include "src/v8.h" | |
9 | |
10 #include "src/wasm/wasm-interpreter.h" | |
11 #include "src/wasm/wasm-macro-gen.h" | |
12 | |
13 using testing::MakeMatcher; | |
14 using testing::Matcher; | |
15 using testing::MatcherInterface; | |
16 using testing::MatchResultListener; | |
17 using testing::StringMatchResultListener; | |
18 | |
19 namespace v8 { | |
20 namespace internal { | |
21 namespace wasm { | |
22 | |
23 #define B1(a) kExprBlock, a, kExprEnd | |
24 #define B2(a, b) kExprBlock, a, b, kExprEnd | |
25 #define B3(a, b, c) kExprBlock, a, b, c, kExprEnd | |
26 | |
27 struct ExpectedTarget { | |
28 pc_t pc; | |
29 ControlTransfer expected; | |
30 }; | |
31 | |
32 // For nicer error messages. | |
33 class ControlTransferMatcher : public MatcherInterface<const ControlTransfer&> { | |
34 public: | |
35 explicit ControlTransferMatcher(pc_t pc, const ControlTransfer& expected) | |
36 : pc_(pc), expected_(expected) {} | |
37 | |
38 void DescribeTo(std::ostream* os) const override { | |
39 *os << "@" << pc_ << " {pcdiff = " << expected_.pcdiff | |
40 << ", spdiff = " << expected_.spdiff | |
41 << ", action = " << expected_.action << "}"; | |
42 } | |
43 | |
44 bool MatchAndExplain(const ControlTransfer& input, | |
45 MatchResultListener* listener) const override { | |
46 if (input.pcdiff != expected_.pcdiff || input.spdiff != expected_.spdiff || | |
47 input.action != expected_.action) { | |
48 *listener << "@" << pc_ << " {pcdiff = " << input.pcdiff | |
49 << ", spdiff = " << input.spdiff | |
50 << ", action = " << input.action << "}"; | |
51 return false; | |
52 } | |
53 return true; | |
54 } | |
55 | |
56 private: | |
57 pc_t pc_; | |
58 const ControlTransfer& expected_; | |
59 }; | |
60 | |
61 class ControlTransferTest : public TestWithZone { | |
62 public: | |
63 void CheckControlTransfers(const byte* start, const byte* end, | |
64 ExpectedTarget* expected_targets, | |
65 size_t num_targets) { | |
66 ControlTransferMap map = | |
67 WasmInterpreter::ComputeControlTransfersForTesting(zone(), start, end); | |
68 // Check all control targets in the map. | |
69 for (size_t i = 0; i < num_targets; i++) { | |
70 pc_t pc = expected_targets[i].pc; | |
71 auto it = map.find(pc); | |
72 if (it == map.end()) { | |
73 printf("expected control target @ +%zu\n", pc); | |
74 EXPECT_TRUE(false); | |
75 } else { | |
76 ControlTransfer& expected = expected_targets[i].expected; | |
77 ControlTransfer& target = it->second; | |
78 EXPECT_THAT(target, | |
79 MakeMatcher(new ControlTransferMatcher(pc, expected))); | |
80 } | |
81 } | |
82 | |
83 // Check there are no other control targets. | |
84 for (pc_t pc = 0; start + pc < end; pc++) { | |
85 bool found = false; | |
86 for (size_t i = 0; i < num_targets; i++) { | |
87 if (expected_targets[i].pc == pc) { | |
88 found = true; | |
89 break; | |
90 } | |
91 } | |
92 if (found) continue; | |
93 if (map.find(pc) != map.end()) { | |
94 printf("expected no control @ +%zu\n", pc); | |
95 EXPECT_TRUE(false); | |
96 } | |
97 } | |
98 } | |
99 }; | |
100 | |
101 // Macro for simplifying tests below. | |
102 #define EXPECT_TARGETS(...) \ | |
103 do { \ | |
104 ExpectedTarget pairs[] = {__VA_ARGS__}; \ | |
105 CheckControlTransfers(code, code + sizeof(code), pairs, arraysize(pairs)); \ | |
106 } while (false) | |
107 | |
108 TEST_F(ControlTransferTest, SimpleIf) { | |
109 byte code[] = { | |
110 kExprI32Const, // @0 | |
111 0, // +1 | |
112 kExprIf, // @2 | |
113 kExprEnd // @3 | |
114 }; | |
115 EXPECT_TARGETS({2, {2, 0, ControlTransfer::kPushVoid}}, // -- | |
116 {3, {1, 0, ControlTransfer::kPushVoid}}); | |
117 } | |
118 | |
119 TEST_F(ControlTransferTest, SimpleIf1) { | |
120 byte code[] = { | |
121 kExprI32Const, // @0 | |
122 0, // +1 | |
123 kExprIf, // @2 | |
124 kExprNop, // @3 | |
125 kExprEnd // @4 | |
126 }; | |
127 EXPECT_TARGETS({2, {3, 0, ControlTransfer::kPushVoid}}, // -- | |
128 {4, {1, 1, ControlTransfer::kPopAndRepush}}); | |
129 } | |
130 | |
131 TEST_F(ControlTransferTest, SimpleIf2) { | |
132 byte code[] = { | |
133 kExprI32Const, // @0 | |
134 0, // +1 | |
135 kExprIf, // @2 | |
136 kExprNop, // @3 | |
137 kExprNop, // @4 | |
138 kExprEnd // @5 | |
139 }; | |
140 EXPECT_TARGETS({2, {4, 0, ControlTransfer::kPushVoid}}, // -- | |
141 {5, {1, 2, ControlTransfer::kPopAndRepush}}); | |
142 } | |
143 | |
144 TEST_F(ControlTransferTest, SimpleIfElse) { | |
145 byte code[] = { | |
146 kExprI32Const, // @0 | |
147 0, // +1 | |
148 kExprIf, // @1 | |
ahaas
2016/05/24 14:48:27
should this be @2?
titzer
2016/05/24 15:09:52
Done.
| |
149 kExprElse, // @2 | |
150 kExprEnd // @3 | |
151 }; | |
152 EXPECT_TARGETS({2, {2, 0, ControlTransfer::kNoAction}}, // -- | |
153 {3, {2, 0, ControlTransfer::kPushVoid}}, // -- | |
154 {4, {1, 0, ControlTransfer::kPushVoid}}); | |
155 } | |
156 | |
157 TEST_F(ControlTransferTest, SimpleIfElse1) { | |
158 byte code[] = { | |
159 kExprI32Const, // @0 | |
160 0, // +1 | |
161 kExprIf, // @2 | |
162 kExprNop, // @3 | |
163 kExprElse, // @4 | |
164 kExprNop, // @5 | |
165 kExprEnd // @6 | |
166 }; | |
167 EXPECT_TARGETS({2, {3, 0, ControlTransfer::kNoAction}}, // -- | |
168 {4, {3, 1, ControlTransfer::kPopAndRepush}}, // -- | |
169 {6, {1, 1, ControlTransfer::kPopAndRepush}}); | |
170 } | |
171 | |
172 TEST_F(ControlTransferTest, IfBr) { | |
173 byte code[] = { | |
174 kExprI32Const, // @0 | |
175 0, // +1 | |
176 kExprIf, // @2 | |
177 kExprBr, // @3 | |
178 ARITY_0, // +1 | |
179 0, // +1 | |
180 kExprEnd // @6 | |
181 }; | |
182 EXPECT_TARGETS({2, {5, 0, ControlTransfer::kPushVoid}}, // -- | |
183 {3, {4, 0, ControlTransfer::kPushVoid}}, // -- | |
184 {6, {1, 1, ControlTransfer::kPopAndRepush}}); | |
185 } | |
186 | |
187 TEST_F(ControlTransferTest, IfBrElse) { | |
188 byte code[] = { | |
189 kExprI32Const, // @0 | |
190 0, // +1 | |
191 kExprIf, // @2 | |
192 kExprBr, // @3 | |
193 ARITY_0, // +1 | |
194 0, // +1 | |
195 kExprElse, // @6 | |
196 kExprEnd // @7 | |
197 }; | |
198 EXPECT_TARGETS({2, {5, 0, ControlTransfer::kNoAction}}, // -- | |
199 {3, {5, 0, ControlTransfer::kPushVoid}}, // -- | |
200 {6, {2, 1, ControlTransfer::kPopAndRepush}}, // -- | |
201 {7, {1, 0, ControlTransfer::kPushVoid}}); | |
202 } | |
203 | |
204 TEST_F(ControlTransferTest, IfElseBr) { | |
205 byte code[] = { | |
206 kExprI32Const, // @0 | |
207 0, // +1 | |
208 kExprIf, // @2 | |
209 kExprNop, // @3 | |
210 kExprElse, // @4 | |
211 kExprBr, // @5 | |
212 ARITY_0, // +1 | |
213 0, // +1 | |
214 kExprEnd // @8 | |
215 }; | |
216 EXPECT_TARGETS({2, {3, 0, ControlTransfer::kNoAction}}, // -- | |
217 {4, {5, 1, ControlTransfer::kPopAndRepush}}, // -- | |
218 {5, {4, 0, ControlTransfer::kPushVoid}}, // -- | |
219 {8, {1, 1, ControlTransfer::kPopAndRepush}}); | |
220 } | |
221 | |
222 TEST_F(ControlTransferTest, BlockEmpty) { | |
223 byte code[] = { | |
224 kExprBlock, // @0 | |
225 kExprEnd // @1 | |
226 }; | |
227 EXPECT_TARGETS({1, {1, 0, ControlTransfer::kPushVoid}}); | |
228 } | |
229 | |
230 TEST_F(ControlTransferTest, Br0) { | |
231 byte code[] = { | |
232 kExprBlock, // @0 | |
233 kExprBr, // @1 | |
234 ARITY_0, // +1 | |
235 0, // +1 | |
236 kExprEnd // @4 | |
237 }; | |
238 EXPECT_TARGETS({1, {4, 0, ControlTransfer::kPushVoid}}, | |
239 {4, {1, 1, ControlTransfer::kPopAndRepush}}); | |
240 } | |
241 | |
242 TEST_F(ControlTransferTest, Br1) { | |
243 byte code[] = { | |
244 kExprBlock, // @0 | |
245 kExprNop, // @1 | |
246 kExprBr, // @2 | |
247 ARITY_0, // +1 | |
248 0, // +1 | |
249 kExprEnd // @5 | |
250 }; | |
251 EXPECT_TARGETS({2, {4, 1, ControlTransfer::kPopAndRepush}}, // -- | |
252 {5, {1, 2, ControlTransfer::kPopAndRepush}}); | |
253 } | |
254 | |
255 TEST_F(ControlTransferTest, Br2) { | |
256 byte code[] = { | |
257 kExprBlock, // @0 | |
258 kExprNop, // @1 | |
259 kExprNop, // @2 | |
260 kExprBr, // @3 | |
261 ARITY_0, // +1 | |
262 0, // +1 | |
263 kExprEnd // @6 | |
264 }; | |
265 EXPECT_TARGETS({3, {4, 2, ControlTransfer::kPopAndRepush}}, // -- | |
266 {6, {1, 3, ControlTransfer::kPopAndRepush}}); | |
267 } | |
268 | |
269 TEST_F(ControlTransferTest, Br0b) { | |
270 byte code[] = { | |
271 kExprBlock, // @0 | |
272 kExprBr, // @1 | |
273 ARITY_0, // +1 | |
274 0, // +1 | |
275 kExprNop, // @4 | |
276 kExprEnd // @5 | |
277 }; | |
278 EXPECT_TARGETS({1, {5, 0, ControlTransfer::kPushVoid}}, // -- | |
279 {5, {1, 2, ControlTransfer::kPopAndRepush}}); | |
280 } | |
281 | |
282 TEST_F(ControlTransferTest, Br0c) { | |
283 byte code[] = { | |
284 kExprBlock, // @0 | |
285 kExprBr, // @1 | |
286 ARITY_0, // +1 | |
287 0, // +1 | |
288 kExprNop, // @4 | |
289 kExprNop, // @5 | |
290 kExprEnd // @6 | |
291 }; | |
292 EXPECT_TARGETS({1, {6, 0, ControlTransfer::kPushVoid}}, // -- | |
293 {6, {1, 3, ControlTransfer::kPopAndRepush}}); | |
294 } | |
295 | |
296 TEST_F(ControlTransferTest, SimpleLoop1) { | |
297 byte code[] = { | |
298 kExprLoop, // @0 | |
299 kExprBr, // @1 | |
300 ARITY_0, // +1 | |
301 0, // +1 | |
302 kExprEnd // @4 | |
303 }; | |
304 EXPECT_TARGETS({1, {-1, 0, ControlTransfer::kNoAction}}, // -- | |
305 {4, {1, 1, ControlTransfer::kPopAndRepush}}); | |
306 } | |
307 | |
308 TEST_F(ControlTransferTest, SimpleLoop2) { | |
309 byte code[] = { | |
310 kExprLoop, // @0 | |
311 kExprNop, // @1 | |
312 kExprBr, // @2 | |
313 ARITY_0, // +1 | |
314 0, // +1 | |
315 kExprEnd // @5 | |
316 }; | |
317 EXPECT_TARGETS({2, {-2, 1, ControlTransfer::kNoAction}}, // -- | |
318 {5, {1, 2, ControlTransfer::kPopAndRepush}}); | |
319 } | |
320 | |
321 TEST_F(ControlTransferTest, SimpleLoopExit1) { | |
322 byte code[] = { | |
323 kExprLoop, // @0 | |
324 kExprBr, // @1 | |
325 ARITY_0, // +1 | |
326 1, // +1 | |
327 kExprEnd // @4 | |
328 }; | |
329 EXPECT_TARGETS({1, {4, 0, ControlTransfer::kPushVoid}}, // -- | |
330 {4, {1, 1, ControlTransfer::kPopAndRepush}}); | |
331 } | |
332 | |
333 TEST_F(ControlTransferTest, SimpleLoopExit2) { | |
334 byte code[] = { | |
335 kExprLoop, // @0 | |
336 kExprNop, // @1 | |
337 kExprBr, // @2 | |
338 ARITY_0, // +1 | |
339 1, // +1 | |
340 kExprEnd // @5 | |
341 }; | |
342 EXPECT_TARGETS({2, {4, 1, ControlTransfer::kPopAndRepush}}, // -- | |
343 {5, {1, 2, ControlTransfer::kPopAndRepush}}); | |
344 } | |
345 | |
346 TEST_F(ControlTransferTest, BrTable0) { | |
347 byte code[] = { | |
348 kExprBlock, // @0 | |
349 kExprI8Const, // @1 | |
350 0, // +1 | |
351 kExprBrTable, // @3 | |
352 ARITY_0, // +1 | |
353 0, // +1 | |
354 U32_LE(0), // +4 | |
355 kExprEnd // @10 | |
356 }; | |
357 EXPECT_TARGETS({3, {8, 0, ControlTransfer::kPushVoid}}, // -- | |
358 {10, {1, 1, ControlTransfer::kPopAndRepush}}); | |
359 } | |
360 | |
361 TEST_F(ControlTransferTest, BrTable1) { | |
362 byte code[] = { | |
363 kExprBlock, // @0 | |
364 kExprI8Const, // @1 | |
365 0, // +1 | |
366 kExprBrTable, // @3 | |
367 ARITY_0, // +1 | |
368 1, // +1 | |
369 U32_LE(0), // +4 | |
370 U32_LE(0), // +4 | |
371 kExprEnd // @14 | |
372 }; | |
373 EXPECT_TARGETS({3, {12, 0, ControlTransfer::kPushVoid}}, // -- | |
374 {4, {11, 0, ControlTransfer::kPushVoid}}, // -- | |
375 {14, {1, 1, ControlTransfer::kPopAndRepush}}); | |
376 } | |
377 | |
378 TEST_F(ControlTransferTest, BrTable2) { | |
379 byte code[] = { | |
380 kExprBlock, // @0 | |
381 kExprBlock, // @1 | |
382 kExprI8Const, // @2 | |
383 0, // +1 | |
384 kExprBrTable, // @4 | |
385 ARITY_0, // +1 | |
386 2, // +1 | |
387 U32_LE(0), // +4 | |
388 U32_LE(0), // +4 | |
389 U32_LE(1), // +4 | |
390 kExprEnd, // @19 | |
391 kExprEnd // @19 | |
392 }; | |
393 EXPECT_TARGETS({4, {16, 0, ControlTransfer::kPushVoid}}, // -- | |
394 {5, {15, 0, ControlTransfer::kPushVoid}}, // -- | |
395 {6, {15, 0, ControlTransfer::kPushVoid}}, // -- | |
396 {19, {1, 1, ControlTransfer::kPopAndRepush}}, // -- | |
397 {20, {1, 1, ControlTransfer::kPopAndRepush}}); | |
398 } | |
399 | |
400 } // namespace wasm | |
401 } // namespace internal | |
402 } // namespace v8 | |
OLD | NEW |