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/graph-unittest.h" | |
6 | |
7 #include <ostream> // NOLINT(readability/streams) | |
8 | |
9 #include "src/compiler/node-properties-inl.h" | |
10 | |
11 using testing::_; | |
12 using testing::MakeMatcher; | |
13 using testing::MatcherInterface; | |
14 using testing::MatchResultListener; | |
15 using testing::StringMatchResultListener; | |
16 | |
17 namespace v8 { | |
18 namespace internal { | |
19 | |
20 // TODO(bmeurer): Find a new home for these functions. | |
21 template <typename T> | |
22 inline std::ostream& operator<<(std::ostream& os, | |
23 const PrintableUnique<T>& value) { | |
24 return os << value.string(); | |
25 } | |
26 inline std::ostream& operator<<(std::ostream& os, | |
27 const ExternalReference& value) { | |
28 OStringStream ost; | |
29 compiler::StaticParameterTraits<ExternalReference>::PrintTo(ost, value); | |
30 return os << ost.c_str(); | |
31 } | |
32 | |
33 namespace compiler { | |
34 | |
35 GraphTest::GraphTest(int num_parameters) : graph_(zone()) { | |
36 graph()->SetStart(graph()->NewNode(common()->Start(num_parameters))); | |
37 } | |
38 | |
39 | |
40 GraphTest::~GraphTest() {} | |
41 | |
42 | |
43 Node* GraphTest::Parameter(int32_t index) { | |
44 return graph()->NewNode(common()->Parameter(index), graph()->start()); | |
45 } | |
46 | |
47 | |
48 Node* GraphTest::Float64Constant(double value) { | |
49 return graph()->NewNode(common()->Float64Constant(value)); | |
50 } | |
51 | |
52 | |
53 Node* GraphTest::Int32Constant(int32_t value) { | |
54 return graph()->NewNode(common()->Int32Constant(value)); | |
55 } | |
56 | |
57 | |
58 Node* GraphTest::Int64Constant(int64_t value) { | |
59 return graph()->NewNode(common()->Int64Constant(value)); | |
60 } | |
61 | |
62 | |
63 Node* GraphTest::NumberConstant(double value) { | |
64 return graph()->NewNode(common()->NumberConstant(value)); | |
65 } | |
66 | |
67 | |
68 Node* GraphTest::HeapConstant(const PrintableUnique<HeapObject>& value) { | |
69 return graph()->NewNode(common()->HeapConstant(value)); | |
70 } | |
71 | |
72 | |
73 Node* GraphTest::FalseConstant() { | |
74 return HeapConstant(PrintableUnique<HeapObject>::CreateImmovable( | |
75 zone(), factory()->false_value())); | |
76 } | |
77 | |
78 | |
79 Node* GraphTest::TrueConstant() { | |
80 return HeapConstant(PrintableUnique<HeapObject>::CreateImmovable( | |
81 zone(), factory()->true_value())); | |
82 } | |
83 | |
84 | |
85 Matcher<Node*> GraphTest::IsFalseConstant() { | |
86 return IsHeapConstant(PrintableUnique<HeapObject>::CreateImmovable( | |
87 zone(), factory()->false_value())); | |
88 } | |
89 | |
90 | |
91 Matcher<Node*> GraphTest::IsTrueConstant() { | |
92 return IsHeapConstant(PrintableUnique<HeapObject>::CreateImmovable( | |
93 zone(), factory()->true_value())); | |
94 } | |
95 | |
96 namespace { | |
97 | |
98 template <typename T> | |
99 bool PrintMatchAndExplain(const T& value, const char* value_name, | |
100 const Matcher<T>& value_matcher, | |
101 MatchResultListener* listener) { | |
102 StringMatchResultListener value_listener; | |
103 if (!value_matcher.MatchAndExplain(value, &value_listener)) { | |
104 *listener << "whose " << value_name << " " << value << " doesn't match"; | |
105 if (value_listener.str() != "") { | |
106 *listener << ", " << value_listener.str(); | |
107 } | |
108 return false; | |
109 } | |
110 return true; | |
111 } | |
112 | |
113 | |
114 class NodeMatcher : public MatcherInterface<Node*> { | |
115 public: | |
116 explicit NodeMatcher(IrOpcode::Value opcode) : opcode_(opcode) {} | |
117 | |
118 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
119 *os << "is a " << IrOpcode::Mnemonic(opcode_) << " node"; | |
120 } | |
121 | |
122 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
123 V8_OVERRIDE { | |
124 if (node == NULL) { | |
125 *listener << "which is NULL"; | |
126 return false; | |
127 } | |
128 if (node->opcode() != opcode_) { | |
129 *listener << "whose opcode is " << IrOpcode::Mnemonic(node->opcode()) | |
130 << " but should have been " << IrOpcode::Mnemonic(opcode_); | |
131 return false; | |
132 } | |
133 return true; | |
134 } | |
135 | |
136 private: | |
137 const IrOpcode::Value opcode_; | |
138 }; | |
139 | |
140 | |
141 class IsBranchMatcher V8_FINAL : public NodeMatcher { | |
142 public: | |
143 IsBranchMatcher(const Matcher<Node*>& value_matcher, | |
144 const Matcher<Node*>& control_matcher) | |
145 : NodeMatcher(IrOpcode::kBranch), | |
146 value_matcher_(value_matcher), | |
147 control_matcher_(control_matcher) {} | |
148 | |
149 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
150 NodeMatcher::DescribeTo(os); | |
151 *os << " whose value ("; | |
152 value_matcher_.DescribeTo(os); | |
153 *os << ") and control ("; | |
154 control_matcher_.DescribeTo(os); | |
155 *os << ")"; | |
156 } | |
157 | |
158 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
159 V8_OVERRIDE { | |
160 return (NodeMatcher::MatchAndExplain(node, listener) && | |
161 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), | |
162 "value", value_matcher_, listener) && | |
163 PrintMatchAndExplain(NodeProperties::GetControlInput(node), | |
164 "control", control_matcher_, listener)); | |
165 } | |
166 | |
167 private: | |
168 const Matcher<Node*> value_matcher_; | |
169 const Matcher<Node*> control_matcher_; | |
170 }; | |
171 | |
172 | |
173 class IsMergeMatcher V8_FINAL : public NodeMatcher { | |
174 public: | |
175 IsMergeMatcher(const Matcher<Node*>& control0_matcher, | |
176 const Matcher<Node*>& control1_matcher) | |
177 : NodeMatcher(IrOpcode::kMerge), | |
178 control0_matcher_(control0_matcher), | |
179 control1_matcher_(control1_matcher) {} | |
180 | |
181 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
182 NodeMatcher::DescribeTo(os); | |
183 *os << " whose control0 ("; | |
184 control0_matcher_.DescribeTo(os); | |
185 *os << ") and control1 ("; | |
186 control1_matcher_.DescribeTo(os); | |
187 *os << ")"; | |
188 } | |
189 | |
190 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
191 V8_OVERRIDE { | |
192 return (NodeMatcher::MatchAndExplain(node, listener) && | |
193 PrintMatchAndExplain(NodeProperties::GetControlInput(node, 0), | |
194 "control0", control0_matcher_, listener) && | |
195 PrintMatchAndExplain(NodeProperties::GetControlInput(node, 1), | |
196 "control1", control1_matcher_, listener)); | |
197 } | |
198 | |
199 private: | |
200 const Matcher<Node*> control0_matcher_; | |
201 const Matcher<Node*> control1_matcher_; | |
202 }; | |
203 | |
204 | |
205 class IsControl1Matcher V8_FINAL : public NodeMatcher { | |
206 public: | |
207 IsControl1Matcher(IrOpcode::Value opcode, | |
208 const Matcher<Node*>& control_matcher) | |
209 : NodeMatcher(opcode), control_matcher_(control_matcher) {} | |
210 | |
211 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
212 NodeMatcher::DescribeTo(os); | |
213 *os << " whose control ("; | |
214 control_matcher_.DescribeTo(os); | |
215 *os << ")"; | |
216 } | |
217 | |
218 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
219 V8_OVERRIDE { | |
220 return (NodeMatcher::MatchAndExplain(node, listener) && | |
221 PrintMatchAndExplain(NodeProperties::GetControlInput(node), | |
222 "control", control_matcher_, listener)); | |
223 } | |
224 | |
225 private: | |
226 const Matcher<Node*> control_matcher_; | |
227 }; | |
228 | |
229 | |
230 class IsFinishMatcher V8_FINAL : public NodeMatcher { | |
231 public: | |
232 IsFinishMatcher(const Matcher<Node*>& value_matcher, | |
233 const Matcher<Node*>& effect_matcher) | |
234 : NodeMatcher(IrOpcode::kFinish), | |
235 value_matcher_(value_matcher), | |
236 effect_matcher_(effect_matcher) {} | |
237 | |
238 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
239 NodeMatcher::DescribeTo(os); | |
240 *os << " whose value ("; | |
241 value_matcher_.DescribeTo(os); | |
242 *os << ") and effect ("; | |
243 effect_matcher_.DescribeTo(os); | |
244 *os << ")"; | |
245 } | |
246 | |
247 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
248 V8_OVERRIDE { | |
249 return (NodeMatcher::MatchAndExplain(node, listener) && | |
250 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), | |
251 "value", value_matcher_, listener) && | |
252 PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect", | |
253 effect_matcher_, listener)); | |
254 } | |
255 | |
256 private: | |
257 const Matcher<Node*> value_matcher_; | |
258 const Matcher<Node*> effect_matcher_; | |
259 }; | |
260 | |
261 | |
262 template <typename T> | |
263 class IsConstantMatcher V8_FINAL : public NodeMatcher { | |
264 public: | |
265 IsConstantMatcher(IrOpcode::Value opcode, const Matcher<T>& value_matcher) | |
266 : NodeMatcher(opcode), value_matcher_(value_matcher) {} | |
267 | |
268 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
269 NodeMatcher::DescribeTo(os); | |
270 *os << " whose value ("; | |
271 value_matcher_.DescribeTo(os); | |
272 *os << ")"; | |
273 } | |
274 | |
275 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
276 V8_OVERRIDE { | |
277 return (NodeMatcher::MatchAndExplain(node, listener) && | |
278 PrintMatchAndExplain(OpParameter<T>(node), "value", value_matcher_, | |
279 listener)); | |
280 } | |
281 | |
282 private: | |
283 const Matcher<T> value_matcher_; | |
284 }; | |
285 | |
286 | |
287 class IsPhiMatcher V8_FINAL : public NodeMatcher { | |
288 public: | |
289 IsPhiMatcher(const Matcher<Node*>& value0_matcher, | |
290 const Matcher<Node*>& value1_matcher, | |
291 const Matcher<Node*>& control_matcher) | |
292 : NodeMatcher(IrOpcode::kPhi), | |
293 value0_matcher_(value0_matcher), | |
294 value1_matcher_(value1_matcher), | |
295 control_matcher_(control_matcher) {} | |
296 | |
297 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
298 NodeMatcher::DescribeTo(os); | |
299 *os << " whose value0 ("; | |
300 value0_matcher_.DescribeTo(os); | |
301 *os << "), value1 ("; | |
302 value1_matcher_.DescribeTo(os); | |
303 *os << ") and control ("; | |
304 control_matcher_.DescribeTo(os); | |
305 *os << ")"; | |
306 } | |
307 | |
308 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
309 V8_OVERRIDE { | |
310 return (NodeMatcher::MatchAndExplain(node, listener) && | |
311 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), | |
312 "value0", value0_matcher_, listener) && | |
313 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), | |
314 "value1", value1_matcher_, listener) && | |
315 PrintMatchAndExplain(NodeProperties::GetControlInput(node), | |
316 "control", control_matcher_, listener)); | |
317 } | |
318 | |
319 private: | |
320 const Matcher<Node*> value0_matcher_; | |
321 const Matcher<Node*> value1_matcher_; | |
322 const Matcher<Node*> control_matcher_; | |
323 }; | |
324 | |
325 | |
326 class IsProjectionMatcher V8_FINAL : public NodeMatcher { | |
327 public: | |
328 IsProjectionMatcher(const Matcher<int32_t>& index_matcher, | |
329 const Matcher<Node*>& base_matcher) | |
330 : NodeMatcher(IrOpcode::kProjection), | |
331 index_matcher_(index_matcher), | |
332 base_matcher_(base_matcher) {} | |
333 | |
334 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
335 NodeMatcher::DescribeTo(os); | |
336 *os << " whose index ("; | |
337 index_matcher_.DescribeTo(os); | |
338 *os << ") and base ("; | |
339 base_matcher_.DescribeTo(os); | |
340 *os << ")"; | |
341 } | |
342 | |
343 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
344 V8_OVERRIDE { | |
345 return (NodeMatcher::MatchAndExplain(node, listener) && | |
346 PrintMatchAndExplain(OpParameter<int32_t>(node), "index", | |
347 index_matcher_, listener) && | |
348 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base", | |
349 base_matcher_, listener)); | |
350 } | |
351 | |
352 private: | |
353 const Matcher<int32_t> index_matcher_; | |
354 const Matcher<Node*> base_matcher_; | |
355 }; | |
356 | |
357 | |
358 class IsCallMatcher V8_FINAL : public NodeMatcher { | |
359 public: | |
360 IsCallMatcher(const Matcher<CallDescriptor*>& descriptor_matcher, | |
361 const Matcher<Node*>& value0_matcher, | |
362 const Matcher<Node*>& value1_matcher, | |
363 const Matcher<Node*>& value2_matcher, | |
364 const Matcher<Node*>& value3_matcher, | |
365 const Matcher<Node*>& effect_matcher, | |
366 const Matcher<Node*>& control_matcher) | |
367 : NodeMatcher(IrOpcode::kCall), | |
368 descriptor_matcher_(descriptor_matcher), | |
369 value0_matcher_(value0_matcher), | |
370 value1_matcher_(value1_matcher), | |
371 value2_matcher_(value2_matcher), | |
372 value3_matcher_(value3_matcher), | |
373 effect_matcher_(effect_matcher), | |
374 control_matcher_(control_matcher) {} | |
375 | |
376 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
377 NodeMatcher::DescribeTo(os); | |
378 *os << " whose value0 ("; | |
379 value0_matcher_.DescribeTo(os); | |
380 *os << ") and value1 ("; | |
381 value1_matcher_.DescribeTo(os); | |
382 *os << ") and value2 ("; | |
383 value2_matcher_.DescribeTo(os); | |
384 *os << ") and value3 ("; | |
385 value3_matcher_.DescribeTo(os); | |
386 *os << ") and effect ("; | |
387 effect_matcher_.DescribeTo(os); | |
388 *os << ") and control ("; | |
389 control_matcher_.DescribeTo(os); | |
390 *os << ")"; | |
391 } | |
392 | |
393 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
394 V8_OVERRIDE { | |
395 return (NodeMatcher::MatchAndExplain(node, listener) && | |
396 PrintMatchAndExplain(OpParameter<CallDescriptor*>(node), | |
397 "descriptor", descriptor_matcher_, listener) && | |
398 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), | |
399 "value0", value0_matcher_, listener) && | |
400 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), | |
401 "value1", value1_matcher_, listener) && | |
402 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 2), | |
403 "value2", value2_matcher_, listener) && | |
404 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 3), | |
405 "value3", value3_matcher_, listener) && | |
406 PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect", | |
407 effect_matcher_, listener) && | |
408 PrintMatchAndExplain(NodeProperties::GetControlInput(node), | |
409 "control", control_matcher_, listener)); | |
410 } | |
411 | |
412 private: | |
413 const Matcher<CallDescriptor*> descriptor_matcher_; | |
414 const Matcher<Node*> value0_matcher_; | |
415 const Matcher<Node*> value1_matcher_; | |
416 const Matcher<Node*> value2_matcher_; | |
417 const Matcher<Node*> value3_matcher_; | |
418 const Matcher<Node*> effect_matcher_; | |
419 const Matcher<Node*> control_matcher_; | |
420 }; | |
421 | |
422 | |
423 class IsLoadMatcher V8_FINAL : public NodeMatcher { | |
424 public: | |
425 IsLoadMatcher(const Matcher<MachineType>& type_matcher, | |
426 const Matcher<Node*>& base_matcher, | |
427 const Matcher<Node*>& index_matcher, | |
428 const Matcher<Node*>& effect_matcher) | |
429 : NodeMatcher(IrOpcode::kLoad), | |
430 type_matcher_(type_matcher), | |
431 base_matcher_(base_matcher), | |
432 index_matcher_(index_matcher), | |
433 effect_matcher_(effect_matcher) {} | |
434 | |
435 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
436 NodeMatcher::DescribeTo(os); | |
437 *os << " whose type ("; | |
438 type_matcher_.DescribeTo(os); | |
439 *os << "), base ("; | |
440 base_matcher_.DescribeTo(os); | |
441 *os << "), index ("; | |
442 index_matcher_.DescribeTo(os); | |
443 *os << ") and effect ("; | |
444 effect_matcher_.DescribeTo(os); | |
445 *os << ")"; | |
446 } | |
447 | |
448 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
449 V8_OVERRIDE { | |
450 return (NodeMatcher::MatchAndExplain(node, listener) && | |
451 PrintMatchAndExplain(OpParameter<MachineType>(node), "type", | |
452 type_matcher_, listener) && | |
453 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base", | |
454 base_matcher_, listener) && | |
455 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), | |
456 "index", index_matcher_, listener) && | |
457 PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect", | |
458 effect_matcher_, listener)); | |
459 } | |
460 | |
461 private: | |
462 const Matcher<MachineType> type_matcher_; | |
463 const Matcher<Node*> base_matcher_; | |
464 const Matcher<Node*> index_matcher_; | |
465 const Matcher<Node*> effect_matcher_; | |
466 }; | |
467 | |
468 | |
469 class IsStoreMatcher V8_FINAL : public NodeMatcher { | |
470 public: | |
471 IsStoreMatcher(const Matcher<MachineType>& type_matcher, | |
472 const Matcher<WriteBarrierKind> write_barrier_matcher, | |
473 const Matcher<Node*>& base_matcher, | |
474 const Matcher<Node*>& index_matcher, | |
475 const Matcher<Node*>& value_matcher, | |
476 const Matcher<Node*>& effect_matcher, | |
477 const Matcher<Node*>& control_matcher) | |
478 : NodeMatcher(IrOpcode::kStore), | |
479 type_matcher_(type_matcher), | |
480 write_barrier_matcher_(write_barrier_matcher), | |
481 base_matcher_(base_matcher), | |
482 index_matcher_(index_matcher), | |
483 value_matcher_(value_matcher), | |
484 effect_matcher_(effect_matcher), | |
485 control_matcher_(control_matcher) {} | |
486 | |
487 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
488 NodeMatcher::DescribeTo(os); | |
489 *os << " whose type ("; | |
490 type_matcher_.DescribeTo(os); | |
491 *os << "), write barrier ("; | |
492 write_barrier_matcher_.DescribeTo(os); | |
493 *os << "), base ("; | |
494 base_matcher_.DescribeTo(os); | |
495 *os << "), index ("; | |
496 index_matcher_.DescribeTo(os); | |
497 *os << "), value ("; | |
498 value_matcher_.DescribeTo(os); | |
499 *os << "), effect ("; | |
500 effect_matcher_.DescribeTo(os); | |
501 *os << ") and control ("; | |
502 control_matcher_.DescribeTo(os); | |
503 *os << ")"; | |
504 } | |
505 | |
506 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
507 V8_OVERRIDE { | |
508 return (NodeMatcher::MatchAndExplain(node, listener) && | |
509 PrintMatchAndExplain( | |
510 OpParameter<StoreRepresentation>(node).machine_type, "type", | |
511 type_matcher_, listener) && | |
512 PrintMatchAndExplain( | |
513 OpParameter<StoreRepresentation>(node).write_barrier_kind, | |
514 "write barrier", write_barrier_matcher_, listener) && | |
515 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base", | |
516 base_matcher_, listener) && | |
517 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), | |
518 "index", index_matcher_, listener) && | |
519 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 2), | |
520 "value", value_matcher_, listener) && | |
521 PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect", | |
522 effect_matcher_, listener) && | |
523 PrintMatchAndExplain(NodeProperties::GetControlInput(node), | |
524 "control", control_matcher_, listener)); | |
525 } | |
526 | |
527 private: | |
528 const Matcher<MachineType> type_matcher_; | |
529 const Matcher<WriteBarrierKind> write_barrier_matcher_; | |
530 const Matcher<Node*> base_matcher_; | |
531 const Matcher<Node*> index_matcher_; | |
532 const Matcher<Node*> value_matcher_; | |
533 const Matcher<Node*> effect_matcher_; | |
534 const Matcher<Node*> control_matcher_; | |
535 }; | |
536 | |
537 | |
538 class IsBinopMatcher V8_FINAL : public NodeMatcher { | |
539 public: | |
540 IsBinopMatcher(IrOpcode::Value opcode, const Matcher<Node*>& lhs_matcher, | |
541 const Matcher<Node*>& rhs_matcher) | |
542 : NodeMatcher(opcode), | |
543 lhs_matcher_(lhs_matcher), | |
544 rhs_matcher_(rhs_matcher) {} | |
545 | |
546 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
547 NodeMatcher::DescribeTo(os); | |
548 *os << " whose lhs ("; | |
549 lhs_matcher_.DescribeTo(os); | |
550 *os << ") and rhs ("; | |
551 rhs_matcher_.DescribeTo(os); | |
552 *os << ")"; | |
553 } | |
554 | |
555 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
556 V8_OVERRIDE { | |
557 return (NodeMatcher::MatchAndExplain(node, listener) && | |
558 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "lhs", | |
559 lhs_matcher_, listener) && | |
560 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), "rhs", | |
561 rhs_matcher_, listener)); | |
562 } | |
563 | |
564 private: | |
565 const Matcher<Node*> lhs_matcher_; | |
566 const Matcher<Node*> rhs_matcher_; | |
567 }; | |
568 | |
569 | |
570 class IsUnopMatcher V8_FINAL : public NodeMatcher { | |
571 public: | |
572 IsUnopMatcher(IrOpcode::Value opcode, const Matcher<Node*>& input_matcher) | |
573 : NodeMatcher(opcode), input_matcher_(input_matcher) {} | |
574 | |
575 virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE { | |
576 NodeMatcher::DescribeTo(os); | |
577 *os << " whose input ("; | |
578 input_matcher_.DescribeTo(os); | |
579 *os << ")"; | |
580 } | |
581 | |
582 virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const | |
583 V8_OVERRIDE { | |
584 return (NodeMatcher::MatchAndExplain(node, listener) && | |
585 PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), | |
586 "input", input_matcher_, listener)); | |
587 } | |
588 | |
589 private: | |
590 const Matcher<Node*> input_matcher_; | |
591 }; | |
592 } | |
593 | |
594 | |
595 Matcher<Node*> IsBranch(const Matcher<Node*>& value_matcher, | |
596 const Matcher<Node*>& control_matcher) { | |
597 return MakeMatcher(new IsBranchMatcher(value_matcher, control_matcher)); | |
598 } | |
599 | |
600 | |
601 Matcher<Node*> IsMerge(const Matcher<Node*>& control0_matcher, | |
602 const Matcher<Node*>& control1_matcher) { | |
603 return MakeMatcher(new IsMergeMatcher(control0_matcher, control1_matcher)); | |
604 } | |
605 | |
606 | |
607 Matcher<Node*> IsIfTrue(const Matcher<Node*>& control_matcher) { | |
608 return MakeMatcher(new IsControl1Matcher(IrOpcode::kIfTrue, control_matcher)); | |
609 } | |
610 | |
611 | |
612 Matcher<Node*> IsIfFalse(const Matcher<Node*>& control_matcher) { | |
613 return MakeMatcher( | |
614 new IsControl1Matcher(IrOpcode::kIfFalse, control_matcher)); | |
615 } | |
616 | |
617 | |
618 Matcher<Node*> IsControlEffect(const Matcher<Node*>& control_matcher) { | |
619 return MakeMatcher( | |
620 new IsControl1Matcher(IrOpcode::kControlEffect, control_matcher)); | |
621 } | |
622 | |
623 | |
624 Matcher<Node*> IsValueEffect(const Matcher<Node*>& value_matcher) { | |
625 return MakeMatcher(new IsUnopMatcher(IrOpcode::kValueEffect, value_matcher)); | |
626 } | |
627 | |
628 | |
629 Matcher<Node*> IsFinish(const Matcher<Node*>& value_matcher, | |
630 const Matcher<Node*>& effect_matcher) { | |
631 return MakeMatcher(new IsFinishMatcher(value_matcher, effect_matcher)); | |
632 } | |
633 | |
634 | |
635 Matcher<Node*> IsExternalConstant( | |
636 const Matcher<ExternalReference>& value_matcher) { | |
637 return MakeMatcher(new IsConstantMatcher<ExternalReference>( | |
638 IrOpcode::kExternalConstant, value_matcher)); | |
639 } | |
640 | |
641 | |
642 Matcher<Node*> IsHeapConstant( | |
643 const Matcher<PrintableUnique<HeapObject> >& value_matcher) { | |
644 return MakeMatcher(new IsConstantMatcher<PrintableUnique<HeapObject> >( | |
645 IrOpcode::kHeapConstant, value_matcher)); | |
646 } | |
647 | |
648 | |
649 Matcher<Node*> IsInt32Constant(const Matcher<int32_t>& value_matcher) { | |
650 return MakeMatcher( | |
651 new IsConstantMatcher<int32_t>(IrOpcode::kInt32Constant, value_matcher)); | |
652 } | |
653 | |
654 | |
655 Matcher<Node*> IsInt64Constant(const Matcher<int64_t>& value_matcher) { | |
656 return MakeMatcher( | |
657 new IsConstantMatcher<int64_t>(IrOpcode::kInt64Constant, value_matcher)); | |
658 } | |
659 | |
660 | |
661 Matcher<Node*> IsFloat64Constant(const Matcher<double>& value_matcher) { | |
662 return MakeMatcher( | |
663 new IsConstantMatcher<double>(IrOpcode::kFloat64Constant, value_matcher)); | |
664 } | |
665 | |
666 | |
667 Matcher<Node*> IsNumberConstant(const Matcher<double>& value_matcher) { | |
668 return MakeMatcher( | |
669 new IsConstantMatcher<double>(IrOpcode::kNumberConstant, value_matcher)); | |
670 } | |
671 | |
672 | |
673 Matcher<Node*> IsPhi(const Matcher<Node*>& value0_matcher, | |
674 const Matcher<Node*>& value1_matcher, | |
675 const Matcher<Node*>& merge_matcher) { | |
676 return MakeMatcher( | |
677 new IsPhiMatcher(value0_matcher, value1_matcher, merge_matcher)); | |
678 } | |
679 | |
680 | |
681 Matcher<Node*> IsProjection(const Matcher<int32_t>& index_matcher, | |
682 const Matcher<Node*>& base_matcher) { | |
683 return MakeMatcher(new IsProjectionMatcher(index_matcher, base_matcher)); | |
684 } | |
685 | |
686 | |
687 Matcher<Node*> IsCall(const Matcher<CallDescriptor*>& descriptor_matcher, | |
688 const Matcher<Node*>& value0_matcher, | |
689 const Matcher<Node*>& value1_matcher, | |
690 const Matcher<Node*>& value2_matcher, | |
691 const Matcher<Node*>& value3_matcher, | |
692 const Matcher<Node*>& effect_matcher, | |
693 const Matcher<Node*>& control_matcher) { | |
694 return MakeMatcher(new IsCallMatcher( | |
695 descriptor_matcher, value0_matcher, value1_matcher, value2_matcher, | |
696 value3_matcher, effect_matcher, control_matcher)); | |
697 } | |
698 | |
699 | |
700 Matcher<Node*> IsLoad(const Matcher<MachineType>& type_matcher, | |
701 const Matcher<Node*>& base_matcher, | |
702 const Matcher<Node*>& index_matcher, | |
703 const Matcher<Node*>& effect_matcher) { | |
704 return MakeMatcher(new IsLoadMatcher(type_matcher, base_matcher, | |
705 index_matcher, effect_matcher)); | |
706 } | |
707 | |
708 | |
709 Matcher<Node*> IsStore(const Matcher<MachineType>& type_matcher, | |
710 const Matcher<WriteBarrierKind>& write_barrier_matcher, | |
711 const Matcher<Node*>& base_matcher, | |
712 const Matcher<Node*>& index_matcher, | |
713 const Matcher<Node*>& value_matcher, | |
714 const Matcher<Node*>& effect_matcher, | |
715 const Matcher<Node*>& control_matcher) { | |
716 return MakeMatcher(new IsStoreMatcher( | |
717 type_matcher, write_barrier_matcher, base_matcher, index_matcher, | |
718 value_matcher, effect_matcher, control_matcher)); | |
719 } | |
720 | |
721 | |
722 #define IS_BINOP_MATCHER(Name) \ | |
723 Matcher<Node*> Is##Name(const Matcher<Node*>& lhs_matcher, \ | |
724 const Matcher<Node*>& rhs_matcher) { \ | |
725 return MakeMatcher( \ | |
726 new IsBinopMatcher(IrOpcode::k##Name, lhs_matcher, rhs_matcher)); \ | |
727 } | |
728 IS_BINOP_MATCHER(Word32And) | |
729 IS_BINOP_MATCHER(Word32Sar) | |
730 IS_BINOP_MATCHER(Word32Shl) | |
731 IS_BINOP_MATCHER(Word32Ror) | |
732 IS_BINOP_MATCHER(Word32Equal) | |
733 IS_BINOP_MATCHER(Word64And) | |
734 IS_BINOP_MATCHER(Word64Sar) | |
735 IS_BINOP_MATCHER(Word64Shl) | |
736 IS_BINOP_MATCHER(Word64Equal) | |
737 IS_BINOP_MATCHER(Int32AddWithOverflow) | |
738 IS_BINOP_MATCHER(Uint32LessThanOrEqual) | |
739 #undef IS_BINOP_MATCHER | |
740 | |
741 | |
742 #define IS_UNOP_MATCHER(Name) \ | |
743 Matcher<Node*> Is##Name(const Matcher<Node*>& input_matcher) { \ | |
744 return MakeMatcher(new IsUnopMatcher(IrOpcode::k##Name, input_matcher)); \ | |
745 } | |
746 IS_UNOP_MATCHER(ChangeFloat64ToInt32) | |
747 IS_UNOP_MATCHER(ChangeFloat64ToUint32) | |
748 IS_UNOP_MATCHER(ChangeInt32ToFloat64) | |
749 IS_UNOP_MATCHER(ChangeInt32ToInt64) | |
750 IS_UNOP_MATCHER(ChangeUint32ToFloat64) | |
751 IS_UNOP_MATCHER(ChangeUint32ToUint64) | |
752 IS_UNOP_MATCHER(TruncateFloat64ToInt32) | |
753 IS_UNOP_MATCHER(TruncateInt64ToInt32) | |
754 #undef IS_UNOP_MATCHER | |
755 | |
756 } // namespace compiler | |
757 } // namespace internal | |
758 } // namespace v8 | |
OLD | NEW |