OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 the V8 project authors. All rights reserved. | |
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/compiler-unittests/node-matchers.h" | |
6 | |
7 #include <ostream> // NOLINT(readability/streams) | |
8 | |
9 #include "src/compiler/node-properties-inl.h" | |
10 | |
11 using testing::MatcherInterface; | |
12 using testing::MatchResultListener; | |
13 using testing::StringMatchResultListener; | |
14 | |
15 namespace v8 { | |
16 namespace internal { | |
17 | |
18 // TODO(bmeurer): Find a new home for these functions. | |
19 template <typename T> | |
20 inline std::ostream& operator<<(std::ostream& os, | |
21 const PrintableUnique<T>& value) { | |
22 return os << value.string(); | |
23 } | |
24 | |
25 namespace compiler { | |
26 | |
27 namespace { | |
28 | |
29 template <typename T> | |
30 bool PrintMatchAndExplain(const T& value, const char* value_name, | |
31 const Matcher<T>& value_matcher, | |
32 MatchResultListener* listener) { | |
33 StringMatchResultListener value_listener; | |
34 if (!value_matcher.MatchAndExplain(value, &value_listener)) { | |
35 *listener << "whose " << value_name << " " << value << " doesn't match"; | |
36 if (value_listener.str() != "") { | |
37 *listener << ", " << value_listener.str(); | |
38 } | |
39 return false; | |
40 } | |
41 return true; | |
42 } | |
43 | |
44 | |
45 class NodeMatcher : public MatcherInterface<Node*> { | |
46 public: | |
47 explicit NodeMatcher(IrOpcode::Value opcode) : opcode_(opcode) {} | |
48 | |
49 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
50 *os << "is a " << IrOpcode::Mnemonic(opcode_) << " node"; | |
51 } | |
52 | |
53 virtual bool MatchAndExplain(Node* node, | |
54 MatchResultListener* listener) const { | |
Jarin
2014/08/12 08:22:38
Should not this be V8_OVERRIDE?
Benedikt Meurer
2014/08/12 08:24:02
Done.
| |
55 if (node == NULL) { | |
56 *listener << "which is NULL"; | |
57 return false; | |
58 } | |
59 if (node->opcode() != opcode_) { | |
60 *listener << "whose opcode is " << IrOpcode::Mnemonic(node->opcode()); | |
61 return false; | |
62 } | |
63 return true; | |
64 } | |
65 | |
66 private: | |
67 const IrOpcode::Value opcode_; | |
68 }; | |
69 | |
70 | |
71 class IsBranchMatcher V8_FINAL : public NodeMatcher { | |
72 public: | |
73 IsBranchMatcher(const Matcher<Node*>& value_matcher, | |
74 const Matcher<Node*>& control_matcher) | |
75 : NodeMatcher(IrOpcode::kBranch), | |
76 value_matcher_(value_matcher), | |
77 control_matcher_(control_matcher) {} | |
78 | |
79 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
80 NodeMatcher::DescribeTo(os); | |
81 *os << " whose value ("; | |
82 value_matcher_.DescribeTo(os); | |
83 *os << ") and control ("; | |
84 control_matcher_.DescribeTo(os); | |
85 *os << ")"; | |
86 } | |
87 | |
88 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
89 V8_OVERRIDE { | |
90 return (NodeMatcher::MatchAndExplain(node, listener) && | |
91 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), | |
92 "value", value_matcher_, listener) && | |
93 PrintMatchAndExplain(NodeProperties::GetControlInput(node), | |
94 "control", control_matcher_, listener)); | |
95 } | |
96 | |
97 private: | |
98 const Matcher<Node*> value_matcher_; | |
99 const Matcher<Node*> control_matcher_; | |
100 }; | |
101 | |
102 | |
103 template <typename T> | |
104 class IsConstantMatcher V8_FINAL : public NodeMatcher { | |
105 public: | |
106 IsConstantMatcher(IrOpcode::Value opcode, const Matcher<T>& value_matcher) | |
107 : NodeMatcher(opcode), value_matcher_(value_matcher) {} | |
108 | |
109 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
110 NodeMatcher::DescribeTo(os); | |
111 *os << " whose value ("; | |
112 value_matcher_.DescribeTo(os); | |
113 *os << ")"; | |
114 } | |
115 | |
116 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
117 V8_OVERRIDE { | |
118 return (NodeMatcher::MatchAndExplain(node, listener) && | |
119 PrintMatchAndExplain(OpParameter<T>(node), "value", value_matcher_, | |
120 listener)); | |
121 } | |
122 | |
123 private: | |
124 const Matcher<T> value_matcher_; | |
125 }; | |
126 | |
127 | |
128 class IsPhiMatcher V8_FINAL : public NodeMatcher { | |
129 public: | |
130 IsPhiMatcher(const Matcher<Node*>& value0_matcher, | |
131 const Matcher<Node*>& value1_matcher, | |
132 const Matcher<Node*>& control_matcher) | |
133 : NodeMatcher(IrOpcode::kPhi), | |
134 value0_matcher_(value0_matcher), | |
135 value1_matcher_(value1_matcher), | |
136 control_matcher_(control_matcher) {} | |
137 | |
138 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
139 NodeMatcher::DescribeTo(os); | |
140 *os << " whose value0 ("; | |
141 value0_matcher_.DescribeTo(os); | |
142 *os << "), value1 ("; | |
143 value1_matcher_.DescribeTo(os); | |
144 *os << ") and control ("; | |
145 control_matcher_.DescribeTo(os); | |
146 *os << ")"; | |
147 } | |
148 | |
149 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
150 V8_OVERRIDE { | |
151 return (NodeMatcher::MatchAndExplain(node, listener) && | |
152 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), | |
153 "value0", value0_matcher_, listener) && | |
154 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), | |
155 "value1", value1_matcher_, listener) && | |
156 PrintMatchAndExplain(NodeProperties::GetControlInput(node), | |
157 "control", control_matcher_, listener)); | |
158 } | |
159 | |
160 private: | |
161 const Matcher<Node*> value0_matcher_; | |
162 const Matcher<Node*> value1_matcher_; | |
163 const Matcher<Node*> control_matcher_; | |
164 }; | |
165 | |
166 | |
167 class IsProjectionMatcher V8_FINAL : public NodeMatcher { | |
168 public: | |
169 IsProjectionMatcher(const Matcher<int32_t>& index_matcher, | |
170 const Matcher<Node*>& base_matcher) | |
171 : NodeMatcher(IrOpcode::kProjection), | |
172 index_matcher_(index_matcher), | |
173 base_matcher_(base_matcher) {} | |
174 | |
175 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
176 NodeMatcher::DescribeTo(os); | |
177 *os << " whose index ("; | |
178 index_matcher_.DescribeTo(os); | |
179 *os << ") and base ("; | |
180 base_matcher_.DescribeTo(os); | |
181 *os << ")"; | |
182 } | |
183 | |
184 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
185 V8_OVERRIDE { | |
186 return (NodeMatcher::MatchAndExplain(node, listener) && | |
187 PrintMatchAndExplain(OpParameter<int32_t>(node), "index", | |
188 index_matcher_, listener) && | |
189 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base", | |
190 base_matcher_, listener)); | |
191 } | |
192 | |
193 private: | |
194 const Matcher<int32_t> index_matcher_; | |
195 const Matcher<Node*> base_matcher_; | |
196 }; | |
197 | |
198 | |
199 class IsLoadMatcher V8_FINAL : public NodeMatcher { | |
200 public: | |
201 IsLoadMatcher(const Matcher<MachineType>& type_matcher, | |
202 const Matcher<Node*>& base_matcher, | |
203 const Matcher<Node*>& index_matcher, | |
204 const Matcher<Node*>& effect_matcher) | |
205 : NodeMatcher(IrOpcode::kLoad), | |
206 type_matcher_(type_matcher), | |
207 base_matcher_(base_matcher), | |
208 index_matcher_(index_matcher), | |
209 effect_matcher_(effect_matcher) {} | |
210 | |
211 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
212 NodeMatcher::DescribeTo(os); | |
213 *os << " whose type ("; | |
214 type_matcher_.DescribeTo(os); | |
215 *os << "), base ("; | |
216 base_matcher_.DescribeTo(os); | |
217 *os << "), index ("; | |
218 index_matcher_.DescribeTo(os); | |
219 *os << ") and effect ("; | |
220 effect_matcher_.DescribeTo(os); | |
221 *os << ")"; | |
222 } | |
223 | |
224 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
225 V8_OVERRIDE { | |
226 return (NodeMatcher::MatchAndExplain(node, listener) && | |
227 PrintMatchAndExplain(OpParameter<MachineType>(node), "type", | |
228 type_matcher_, listener) && | |
229 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base", | |
230 base_matcher_, listener) && | |
231 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), | |
232 "index", index_matcher_, listener) && | |
233 PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect", | |
234 effect_matcher_, listener)); | |
235 } | |
236 | |
237 private: | |
238 const Matcher<MachineType> type_matcher_; | |
239 const Matcher<Node*> base_matcher_; | |
240 const Matcher<Node*> index_matcher_; | |
241 const Matcher<Node*> effect_matcher_; | |
242 }; | |
243 | |
244 | |
245 class IsStoreMatcher V8_FINAL : public NodeMatcher { | |
246 public: | |
247 IsStoreMatcher(const Matcher<MachineType>& type_matcher, | |
248 const Matcher<WriteBarrierKind> write_barrier_matcher, | |
249 const Matcher<Node*>& base_matcher, | |
250 const Matcher<Node*>& index_matcher, | |
251 const Matcher<Node*>& value_matcher, | |
252 const Matcher<Node*>& effect_matcher, | |
253 const Matcher<Node*>& control_matcher) | |
254 : NodeMatcher(IrOpcode::kStore), | |
255 type_matcher_(type_matcher), | |
256 write_barrier_matcher_(write_barrier_matcher), | |
257 base_matcher_(base_matcher), | |
258 index_matcher_(index_matcher), | |
259 value_matcher_(value_matcher), | |
260 effect_matcher_(effect_matcher), | |
261 control_matcher_(control_matcher) {} | |
262 | |
263 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
264 NodeMatcher::DescribeTo(os); | |
265 *os << " whose type ("; | |
266 type_matcher_.DescribeTo(os); | |
267 *os << "), write barrier ("; | |
268 write_barrier_matcher_.DescribeTo(os); | |
269 *os << "), base ("; | |
270 base_matcher_.DescribeTo(os); | |
271 *os << "), index ("; | |
272 index_matcher_.DescribeTo(os); | |
273 *os << "), value ("; | |
274 value_matcher_.DescribeTo(os); | |
275 *os << "), effect ("; | |
276 effect_matcher_.DescribeTo(os); | |
277 *os << ") and control ("; | |
278 control_matcher_.DescribeTo(os); | |
279 *os << ")"; | |
280 } | |
281 | |
282 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
283 V8_OVERRIDE { | |
284 return (NodeMatcher::MatchAndExplain(node, listener) && | |
285 PrintMatchAndExplain(OpParameter<StoreRepresentation>(node).rep, | |
286 "type", type_matcher_, listener) && | |
287 PrintMatchAndExplain( | |
288 OpParameter<StoreRepresentation>(node).write_barrier_kind, | |
289 "write barrier", write_barrier_matcher_, listener) && | |
290 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base", | |
291 base_matcher_, listener) && | |
292 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), | |
293 "index", index_matcher_, listener) && | |
294 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 2), | |
295 "value", value_matcher_, listener) && | |
296 PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect", | |
297 effect_matcher_, listener) && | |
298 PrintMatchAndExplain(NodeProperties::GetControlInput(node), | |
299 "control", control_matcher_, listener)); | |
300 } | |
301 | |
302 private: | |
303 const Matcher<MachineType> type_matcher_; | |
304 const Matcher<WriteBarrierKind> write_barrier_matcher_; | |
305 const Matcher<Node*> base_matcher_; | |
306 const Matcher<Node*> index_matcher_; | |
307 const Matcher<Node*> value_matcher_; | |
308 const Matcher<Node*> effect_matcher_; | |
309 const Matcher<Node*> control_matcher_; | |
310 }; | |
311 | |
312 | |
313 class IsBinopMatcher V8_FINAL : public NodeMatcher { | |
314 public: | |
315 IsBinopMatcher(IrOpcode::Value opcode, const Matcher<Node*>& lhs_matcher, | |
316 const Matcher<Node*>& rhs_matcher) | |
317 : NodeMatcher(opcode), | |
318 lhs_matcher_(lhs_matcher), | |
319 rhs_matcher_(rhs_matcher) {} | |
320 | |
321 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
322 NodeMatcher::DescribeTo(os); | |
323 *os << " whose lhs ("; | |
324 lhs_matcher_.DescribeTo(os); | |
325 *os << ") and rhs ("; | |
326 rhs_matcher_.DescribeTo(os); | |
327 *os << ")"; | |
328 } | |
329 | |
330 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
331 V8_OVERRIDE { | |
332 return (NodeMatcher::MatchAndExplain(node, listener) && | |
333 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "lhs", | |
334 lhs_matcher_, listener) && | |
335 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), "rhs", | |
336 rhs_matcher_, listener)); | |
337 } | |
338 | |
339 private: | |
340 const Matcher<Node*> lhs_matcher_; | |
341 const Matcher<Node*> rhs_matcher_; | |
342 }; | |
343 | |
344 | |
345 class IsUnopMatcher V8_FINAL : public NodeMatcher { | |
346 public: | |
347 IsUnopMatcher(IrOpcode::Value opcode, const Matcher<Node*>& input_matcher) | |
348 : NodeMatcher(opcode), input_matcher_(input_matcher) {} | |
349 | |
350 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
351 NodeMatcher::DescribeTo(os); | |
352 *os << " whose input ("; | |
353 input_matcher_.DescribeTo(os); | |
354 *os << ")"; | |
355 } | |
356 | |
357 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
358 V8_OVERRIDE { | |
359 return (NodeMatcher::MatchAndExplain(node, listener) && | |
360 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), | |
361 "input", input_matcher_, listener)); | |
362 } | |
363 | |
364 private: | |
365 const Matcher<Node*> input_matcher_; | |
366 }; | |
367 | |
368 } | |
369 | |
370 | |
371 Matcher<Node*> IsBranch(const Matcher<Node*>& value_matcher, | |
372 const Matcher<Node*>& control_matcher) { | |
373 return MakeMatcher(new IsBranchMatcher(value_matcher, control_matcher)); | |
374 } | |
375 | |
376 | |
377 Matcher<Node*> IsInt32Constant(const Matcher<int32_t>& value_matcher) { | |
378 return MakeMatcher( | |
379 new IsConstantMatcher<int32_t>(IrOpcode::kInt32Constant, value_matcher)); | |
380 } | |
381 | |
382 | |
383 Matcher<Node*> IsHeapConstant( | |
384 const Matcher<PrintableUnique<HeapObject> >& value_matcher) { | |
385 return MakeMatcher(new IsConstantMatcher<PrintableUnique<HeapObject> >( | |
386 IrOpcode::kHeapConstant, value_matcher)); | |
387 } | |
388 | |
389 | |
390 Matcher<Node*> IsPhi(const Matcher<Node*>& value0_matcher, | |
391 const Matcher<Node*>& value1_matcher, | |
392 const Matcher<Node*>& merge_matcher) { | |
393 return MakeMatcher( | |
394 new IsPhiMatcher(value0_matcher, value1_matcher, merge_matcher)); | |
395 } | |
396 | |
397 | |
398 Matcher<Node*> IsProjection(const Matcher<int32_t>& index_matcher, | |
399 const Matcher<Node*>& base_matcher) { | |
400 return MakeMatcher(new IsProjectionMatcher(index_matcher, base_matcher)); | |
401 } | |
402 | |
403 | |
404 Matcher<Node*> IsLoad(const Matcher<MachineType>& type_matcher, | |
405 const Matcher<Node*>& base_matcher, | |
406 const Matcher<Node*>& index_matcher, | |
407 const Matcher<Node*>& effect_matcher) { | |
408 return MakeMatcher(new IsLoadMatcher(type_matcher, base_matcher, | |
409 index_matcher, effect_matcher)); | |
410 } | |
411 | |
412 | |
413 Matcher<Node*> IsStore(const Matcher<MachineType>& type_matcher, | |
414 const Matcher<WriteBarrierKind>& write_barrier_matcher, | |
415 const Matcher<Node*>& base_matcher, | |
416 const Matcher<Node*>& index_matcher, | |
417 const Matcher<Node*>& value_matcher, | |
418 const Matcher<Node*>& effect_matcher, | |
419 const Matcher<Node*>& control_matcher) { | |
420 return MakeMatcher(new IsStoreMatcher( | |
421 type_matcher, write_barrier_matcher, base_matcher, index_matcher, | |
422 value_matcher, effect_matcher, control_matcher)); | |
423 } | |
424 | |
425 | |
426 #define IS_BINOP_MATCHER(Name) \ | |
427 Matcher<Node*> Is##Name(const Matcher<Node*>& lhs_matcher, \ | |
428 const Matcher<Node*>& rhs_matcher) { \ | |
429 return MakeMatcher( \ | |
430 new IsBinopMatcher(IrOpcode::k##Name, lhs_matcher, rhs_matcher)); \ | |
431 } | |
432 IS_BINOP_MATCHER(Word32And) | |
433 IS_BINOP_MATCHER(Word32Sar) | |
434 IS_BINOP_MATCHER(Word32Equal) | |
435 IS_BINOP_MATCHER(Word64And) | |
436 IS_BINOP_MATCHER(Word64Sar) | |
437 IS_BINOP_MATCHER(Word64Shl) | |
438 IS_BINOP_MATCHER(Word64Equal) | |
439 IS_BINOP_MATCHER(Int32AddWithOverflow) | |
440 #undef IS_BINOP_MATCHER | |
441 | |
442 | |
443 #define IS_UNOP_MATCHER(Name) \ | |
444 Matcher<Node*> Is##Name(const Matcher<Node*>& input_matcher) { \ | |
445 return MakeMatcher(new IsUnopMatcher(IrOpcode::k##Name, input_matcher)); \ | |
446 } | |
447 IS_UNOP_MATCHER(ConvertInt64ToInt32) | |
448 IS_UNOP_MATCHER(ChangeInt32ToFloat64) | |
449 #undef IS_UNOP_MATCHER | |
450 | |
451 } // namespace compiler | |
452 } // namespace internal | |
453 } // namespace v8 | |
OLD | NEW |