Chromium Code Reviews| 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 |