| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/machine-graph-verifier.h" | 5 #include "src/compiler/machine-graph-verifier.h" |
| 6 | 6 |
| 7 #include "src/compiler/common-operator.h" | 7 #include "src/compiler/common-operator.h" |
| 8 #include "src/compiler/graph.h" | 8 #include "src/compiler/graph.h" |
| 9 #include "src/compiler/linkage.h" | 9 #include "src/compiler/linkage.h" |
| 10 #include "src/compiler/machine-operator.h" | 10 #include "src/compiler/machine-operator.h" |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 | 230 |
| 231 Schedule const* const schedule_; | 231 Schedule const* const schedule_; |
| 232 Linkage const* const linkage_; | 232 Linkage const* const linkage_; |
| 233 ZoneVector<MachineRepresentation> representation_vector_; | 233 ZoneVector<MachineRepresentation> representation_vector_; |
| 234 }; | 234 }; |
| 235 | 235 |
| 236 class MachineRepresentationChecker { | 236 class MachineRepresentationChecker { |
| 237 public: | 237 public: |
| 238 MachineRepresentationChecker( | 238 MachineRepresentationChecker( |
| 239 Schedule const* const schedule, | 239 Schedule const* const schedule, |
| 240 MachineRepresentationInferrer const* const inferrer) | 240 MachineRepresentationInferrer const* const inferrer, bool is_stub) |
| 241 : schedule_(schedule), inferrer_(inferrer) {} | 241 : schedule_(schedule), inferrer_(inferrer), is_stub_(is_stub) {} |
| 242 | 242 |
| 243 void Run() { | 243 void Run() { |
| 244 BasicBlockVector const* blocks = schedule_->all_blocks(); | 244 BasicBlockVector const* blocks = schedule_->all_blocks(); |
| 245 for (BasicBlock* block : *blocks) { | 245 for (BasicBlock* block : *blocks) { |
| 246 for (size_t i = 0; i <= block->NodeCount(); ++i) { | 246 for (size_t i = 0; i <= block->NodeCount(); ++i) { |
| 247 Node const* node = | 247 Node const* node = |
| 248 i < block->NodeCount() ? block->NodeAt(i) : block->control_input(); | 248 i < block->NodeCount() ? block->NodeAt(i) : block->control_input(); |
| 249 if (node == nullptr) { | 249 if (node == nullptr) { |
| 250 DCHECK_EQ(block->NodeCount(), i); | 250 DCHECK_EQ(block->NodeCount(), i); |
| 251 break; | 251 break; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 case IrOpcode::kTruncateFloat64ToFloat32: | 283 case IrOpcode::kTruncateFloat64ToFloat32: |
| 284 case IrOpcode::kChangeFloat64ToInt32: | 284 case IrOpcode::kChangeFloat64ToInt32: |
| 285 case IrOpcode::kChangeFloat64ToUint32: | 285 case IrOpcode::kChangeFloat64ToUint32: |
| 286 case IrOpcode::kRoundFloat64ToInt32: | 286 case IrOpcode::kRoundFloat64ToInt32: |
| 287 case IrOpcode::kFloat64ExtractLowWord32: | 287 case IrOpcode::kFloat64ExtractLowWord32: |
| 288 case IrOpcode::kFloat64ExtractHighWord32: | 288 case IrOpcode::kFloat64ExtractHighWord32: |
| 289 case IrOpcode::kBitcastFloat64ToInt64: | 289 case IrOpcode::kBitcastFloat64ToInt64: |
| 290 CheckValueInputForFloat64Op(node, 0); | 290 CheckValueInputForFloat64Op(node, 0); |
| 291 break; | 291 break; |
| 292 case IrOpcode::kWord64Equal: | 292 case IrOpcode::kWord64Equal: |
| 293 CheckValueInputIsTaggedOrPointer(node, 0); | 293 if (Is64()) { |
| 294 CheckValueInputRepresentationIs( | 294 CheckValueInputIsTaggedOrPointer(node, 0); |
| 295 node, 1, inferrer_->GetRepresentation(node->InputAt(0))); | 295 CheckValueInputIsTaggedOrPointer(node, 1); |
| 296 if (!is_stub_) { |
| 297 CheckValueInputRepresentationIs( |
| 298 node, 1, inferrer_->GetRepresentation(node->InputAt(0))); |
| 299 } |
| 300 } else { |
| 301 CheckValueInputForInt64Op(node, 0); |
| 302 CheckValueInputForInt64Op(node, 1); |
| 303 } |
| 296 break; | 304 break; |
| 297 case IrOpcode::kInt64LessThan: | 305 case IrOpcode::kInt64LessThan: |
| 298 case IrOpcode::kInt64LessThanOrEqual: | 306 case IrOpcode::kInt64LessThanOrEqual: |
| 299 case IrOpcode::kUint64LessThan: | 307 case IrOpcode::kUint64LessThan: |
| 300 case IrOpcode::kUint64LessThanOrEqual: | 308 case IrOpcode::kUint64LessThanOrEqual: |
| 301 CheckValueInputForInt64Op(node, 0); | 309 CheckValueInputForInt64Op(node, 0); |
| 302 CheckValueInputForInt64Op(node, 1); | 310 CheckValueInputForInt64Op(node, 1); |
| 303 break; | 311 break; |
| 304 case IrOpcode::kInt32x4ExtractLane: | 312 case IrOpcode::kInt32x4ExtractLane: |
| 305 CheckValueInputRepresentationIs(node, 0, | 313 CheckValueInputRepresentationIs(node, 0, |
| 306 MachineRepresentation::kSimd128); | 314 MachineRepresentation::kSimd128); |
| 307 break; | 315 break; |
| 308 #define LABEL(opcode) case IrOpcode::k##opcode: | 316 #define LABEL(opcode) case IrOpcode::k##opcode: |
| 309 case IrOpcode::kChangeInt32ToTagged: | 317 case IrOpcode::kChangeInt32ToTagged: |
| 310 case IrOpcode::kChangeUint32ToTagged: | 318 case IrOpcode::kChangeUint32ToTagged: |
| 311 case IrOpcode::kChangeInt32ToFloat64: | 319 case IrOpcode::kChangeInt32ToFloat64: |
| 312 case IrOpcode::kChangeUint32ToFloat64: | 320 case IrOpcode::kChangeUint32ToFloat64: |
| 313 case IrOpcode::kRoundInt32ToFloat32: | 321 case IrOpcode::kRoundInt32ToFloat32: |
| 314 case IrOpcode::kRoundUint32ToFloat32: | 322 case IrOpcode::kRoundUint32ToFloat32: |
| 315 case IrOpcode::kChangeInt32ToInt64: | 323 case IrOpcode::kChangeInt32ToInt64: |
| 316 case IrOpcode::kChangeUint32ToUint64: | 324 case IrOpcode::kChangeUint32ToUint64: |
| 317 MACHINE_UNOP_32_LIST(LABEL) { CheckValueInputForInt32Op(node, 0); } | 325 MACHINE_UNOP_32_LIST(LABEL) { CheckValueInputForInt32Op(node, 0); } |
| 318 break; | 326 break; |
| 319 case IrOpcode::kWord32Equal: | 327 case IrOpcode::kWord32Equal: |
| 328 if (Is32()) { |
| 329 CheckValueInputIsTaggedOrPointer(node, 0); |
| 330 CheckValueInputIsTaggedOrPointer(node, 1); |
| 331 if (!is_stub_) { |
| 332 CheckValueInputRepresentationIs( |
| 333 node, 1, inferrer_->GetRepresentation(node->InputAt(0))); |
| 334 } |
| 335 } else { |
| 336 CheckValueInputForInt32Op(node, 0); |
| 337 CheckValueInputForInt32Op(node, 1); |
| 338 } |
| 339 break; |
| 340 |
| 320 case IrOpcode::kInt32LessThan: | 341 case IrOpcode::kInt32LessThan: |
| 321 case IrOpcode::kInt32LessThanOrEqual: | 342 case IrOpcode::kInt32LessThanOrEqual: |
| 322 case IrOpcode::kUint32LessThan: | 343 case IrOpcode::kUint32LessThan: |
| 323 case IrOpcode::kUint32LessThanOrEqual: | 344 case IrOpcode::kUint32LessThanOrEqual: |
| 324 MACHINE_BINOP_32_LIST(LABEL) { | 345 MACHINE_BINOP_32_LIST(LABEL) { |
| 325 CheckValueInputForInt32Op(node, 0); | 346 CheckValueInputForInt32Op(node, 0); |
| 326 CheckValueInputForInt32Op(node, 1); | 347 CheckValueInputForInt32Op(node, 1); |
| 327 } | 348 } |
| 328 break; | 349 break; |
| 329 MACHINE_BINOP_64_LIST(LABEL) { | 350 MACHINE_BINOP_64_LIST(LABEL) { |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 436 << " in the machine graph is not being checked."; | 457 << " in the machine graph is not being checked."; |
| 437 FATAL(str.str().c_str()); | 458 FATAL(str.str().c_str()); |
| 438 } | 459 } |
| 439 break; | 460 break; |
| 440 } | 461 } |
| 441 } | 462 } |
| 442 } | 463 } |
| 443 } | 464 } |
| 444 | 465 |
| 445 private: | 466 private: |
| 467 static bool Is32() { |
| 468 return MachineType::PointerRepresentation() == |
| 469 MachineRepresentation::kWord32; |
| 470 } |
| 471 static bool Is64() { |
| 472 return MachineType::PointerRepresentation() == |
| 473 MachineRepresentation::kWord64; |
| 474 } |
| 475 |
| 446 void CheckValueInputRepresentationIs(Node const* node, int index, | 476 void CheckValueInputRepresentationIs(Node const* node, int index, |
| 447 MachineRepresentation representation) { | 477 MachineRepresentation representation) { |
| 448 Node const* input = node->InputAt(index); | 478 Node const* input = node->InputAt(index); |
| 449 MachineRepresentation input_representation = | 479 MachineRepresentation input_representation = |
| 450 inferrer_->GetRepresentation(input); | 480 inferrer_->GetRepresentation(input); |
| 451 if (input_representation != representation) { | 481 if (input_representation != representation) { |
| 452 std::stringstream str; | 482 std::stringstream str; |
| 453 str << "TypeError: node #" << node->id() << ":" << *node->op() << ":" | 483 str << "TypeError: node #" << node->id() << ":" << *node->op() |
| 454 << MachineReprToString(input_representation) << " uses node #" | 484 << " uses node #" << input->id() << ":" << *input->op() << ":" |
| 455 << input->id() << ":" << *input->op() << " which doesn't have a " | 485 << input_representation << " which doesn't have a " << representation |
| 456 << MachineReprToString(representation) << " representation."; | 486 << " representation."; |
| 457 FATAL(str.str().c_str()); | 487 FATAL(str.str().c_str()); |
| 458 } | 488 } |
| 459 } | 489 } |
| 460 | 490 |
| 461 void CheckValueInputIsTagged(Node const* node, int index) { | 491 void CheckValueInputIsTagged(Node const* node, int index) { |
| 462 Node const* input = node->InputAt(index); | 492 Node const* input = node->InputAt(index); |
| 463 switch (inferrer_->GetRepresentation(input)) { | 493 switch (inferrer_->GetRepresentation(input)) { |
| 464 case MachineRepresentation::kTagged: | 494 case MachineRepresentation::kTagged: |
| 465 case MachineRepresentation::kTaggedPointer: | 495 case MachineRepresentation::kTaggedPointer: |
| 466 case MachineRepresentation::kTaggedSigned: | 496 case MachineRepresentation::kTaggedSigned: |
| 467 return; | 497 return; |
| 468 default: | 498 default: |
| 469 break; | 499 break; |
| 470 } | 500 } |
| 471 std::ostringstream str; | 501 std::ostringstream str; |
| 472 str << "TypeError: node #" << node->id() << ":" << *node->op() | 502 str << "TypeError: node #" << node->id() << ":" << *node->op() |
| 473 << " uses node #" << input->id() << ":" << *input->op() | 503 << " uses node #" << input->id() << ":" << *input->op() |
| 474 << " which doesn't have a tagged representation."; | 504 << " which doesn't have a tagged representation."; |
| 475 FATAL(str.str().c_str()); | 505 FATAL(str.str().c_str()); |
| 476 } | 506 } |
| 477 | 507 |
| 478 void CheckValueInputIsTaggedOrPointer(Node const* node, int index) { | 508 void CheckValueInputIsTaggedOrPointer(Node const* node, int index) { |
| 479 Node const* input = node->InputAt(index); | 509 Node const* input = node->InputAt(index); |
| 480 switch (inferrer_->GetRepresentation(input)) { | 510 switch (inferrer_->GetRepresentation(input)) { |
| 481 case MachineRepresentation::kTagged: | 511 case MachineRepresentation::kTagged: |
| 482 case MachineRepresentation::kTaggedPointer: | 512 case MachineRepresentation::kTaggedPointer: |
| 483 case MachineRepresentation::kTaggedSigned: | 513 case MachineRepresentation::kTaggedSigned: |
| 484 return; | 514 return; |
| 515 case MachineRepresentation::kBit: |
| 516 case MachineRepresentation::kWord8: |
| 517 case MachineRepresentation::kWord16: |
| 518 case MachineRepresentation::kWord32: |
| 519 if (Is32()) { |
| 520 return; |
| 521 } |
| 522 break; |
| 523 case MachineRepresentation::kWord64: |
| 524 if (Is64()) { |
| 525 return; |
| 526 } |
| 527 break; |
| 485 default: | 528 default: |
| 486 break; | 529 break; |
| 487 } | 530 } |
| 488 if (inferrer_->GetRepresentation(input) != | 531 if (inferrer_->GetRepresentation(input) != |
| 489 MachineType::PointerRepresentation()) { | 532 MachineType::PointerRepresentation()) { |
| 490 std::ostringstream str; | 533 std::ostringstream str; |
| 491 str << "TypeError: node #" << node->id() << ":" << *node->op() | 534 str << "TypeError: node #" << node->id() << ":" << *node->op() |
| 492 << " uses node #" << input->id() << ":" << *input->op() | 535 << " uses node #" << input->id() << ":" << *input->op() |
| 493 << " which doesn't have a tagged or pointer representation."; | 536 << " which doesn't have a tagged or pointer representation."; |
| 494 FATAL(str.str().c_str()); | 537 FATAL(str.str().c_str()); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 str << "TypeError: node #" << input->id() << ":" << *input->op() | 575 str << "TypeError: node #" << input->id() << ":" << *input->op() |
| 533 << " is untyped."; | 576 << " is untyped."; |
| 534 FATAL(str.str().c_str()); | 577 FATAL(str.str().c_str()); |
| 535 break; | 578 break; |
| 536 } | 579 } |
| 537 | 580 |
| 538 default: | 581 default: |
| 539 break; | 582 break; |
| 540 } | 583 } |
| 541 std::ostringstream str; | 584 std::ostringstream str; |
| 542 str << "TypeError: node #" << node->id() << ":" << *node->op() << ":" | 585 str << "TypeError: node #" << node->id() << ":" << *node->op() |
| 543 << input_representation << " uses node #" << input->id() << ":" | 586 << " uses node #" << input->id() << ":" << *input->op() << ":" |
| 544 << *input->op() << " which doesn't have a kWord64 representation."; | 587 << input_representation |
| 588 << " which doesn't have a kWord64 representation."; |
| 545 FATAL(str.str().c_str()); | 589 FATAL(str.str().c_str()); |
| 546 } | 590 } |
| 547 | 591 |
| 548 void CheckValueInputForFloat32Op(Node const* node, int index) { | 592 void CheckValueInputForFloat32Op(Node const* node, int index) { |
| 549 Node const* input = node->InputAt(index); | 593 Node const* input = node->InputAt(index); |
| 550 if (MachineRepresentation::kFloat32 == | 594 if (MachineRepresentation::kFloat32 == |
| 551 inferrer_->GetRepresentation(input)) { | 595 inferrer_->GetRepresentation(input)) { |
| 552 return; | 596 return; |
| 553 } | 597 } |
| 554 std::ostringstream str; | 598 std::ostringstream str; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 583 desc->GetInputType(i).representation(); | 627 desc->GetInputType(i).representation(); |
| 584 if (!IsCompatible(expected_input_type, input_type)) { | 628 if (!IsCompatible(expected_input_type, input_type)) { |
| 585 if (!should_log_error) { | 629 if (!should_log_error) { |
| 586 should_log_error = true; | 630 should_log_error = true; |
| 587 str << "TypeError: node #" << node->id() << ":" << *node->op() | 631 str << "TypeError: node #" << node->id() << ":" << *node->op() |
| 588 << " has wrong type for:" << std::endl; | 632 << " has wrong type for:" << std::endl; |
| 589 } else { | 633 } else { |
| 590 str << std::endl; | 634 str << std::endl; |
| 591 } | 635 } |
| 592 str << " * input " << i << " (" << input->id() << ":" << *input->op() | 636 str << " * input " << i << " (" << input->id() << ":" << *input->op() |
| 593 << ") doesn't have a " << MachineReprToString(expected_input_type) | 637 << ") doesn't have a " << expected_input_type << " representation."; |
| 594 << " representation."; | |
| 595 } | 638 } |
| 596 } | 639 } |
| 597 if (should_log_error) { | 640 if (should_log_error) { |
| 598 FATAL(str.str().c_str()); | 641 FATAL(str.str().c_str()); |
| 599 } | 642 } |
| 600 } | 643 } |
| 601 | 644 |
| 602 bool Intersect(MachineRepresentation lhs, MachineRepresentation rhs) { | 645 bool Intersect(MachineRepresentation lhs, MachineRepresentation rhs) { |
| 603 return (GetRepresentationProperties(lhs) & | 646 return (GetRepresentationProperties(lhs) & |
| 604 GetRepresentationProperties(rhs)) != 0; | 647 GetRepresentationProperties(rhs)) != 0; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 actual == MachineRepresentation::kWord16 || | 695 actual == MachineRepresentation::kWord16 || |
| 653 actual == MachineRepresentation::kWord32); | 696 actual == MachineRepresentation::kWord32); |
| 654 case MachineRepresentation::kNone: | 697 case MachineRepresentation::kNone: |
| 655 UNREACHABLE(); | 698 UNREACHABLE(); |
| 656 } | 699 } |
| 657 return false; | 700 return false; |
| 658 } | 701 } |
| 659 | 702 |
| 660 Schedule const* const schedule_; | 703 Schedule const* const schedule_; |
| 661 MachineRepresentationInferrer const* const inferrer_; | 704 MachineRepresentationInferrer const* const inferrer_; |
| 705 bool is_stub_; |
| 662 }; | 706 }; |
| 663 | 707 |
| 664 } // namespace | 708 } // namespace |
| 665 | 709 |
| 666 void MachineGraphVerifier::Run(Graph* graph, Schedule const* const schedule, | 710 void MachineGraphVerifier::Run(Graph* graph, Schedule const* const schedule, |
| 667 Linkage* linkage, Zone* temp_zone) { | 711 Linkage* linkage, bool is_stub, |
| 712 Zone* temp_zone) { |
| 668 MachineRepresentationInferrer representation_inferrer(schedule, graph, | 713 MachineRepresentationInferrer representation_inferrer(schedule, graph, |
| 669 linkage, temp_zone); | 714 linkage, temp_zone); |
| 670 MachineRepresentationChecker checker(schedule, &representation_inferrer); | 715 MachineRepresentationChecker checker(schedule, &representation_inferrer, |
| 716 is_stub); |
| 671 checker.Run(); | 717 checker.Run(); |
| 672 } | 718 } |
| 673 | 719 |
| 674 } // namespace compiler | 720 } // namespace compiler |
| 675 } // namespace internal | 721 } // namespace internal |
| 676 } // namespace v8 | 722 } // namespace v8 |
| OLD | NEW |