| 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 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 | 268 |
| 269 Schedule const* const schedule_; | 269 Schedule const* const schedule_; |
| 270 Linkage const* const linkage_; | 270 Linkage const* const linkage_; |
| 271 ZoneVector<MachineRepresentation> representation_vector_; | 271 ZoneVector<MachineRepresentation> representation_vector_; |
| 272 }; | 272 }; |
| 273 | 273 |
| 274 class MachineRepresentationChecker { | 274 class MachineRepresentationChecker { |
| 275 public: | 275 public: |
| 276 MachineRepresentationChecker( | 276 MachineRepresentationChecker( |
| 277 Schedule const* const schedule, | 277 Schedule const* const schedule, |
| 278 MachineRepresentationInferrer const* const inferrer, bool is_stub) | 278 MachineRepresentationInferrer const* const inferrer, bool is_stub, |
| 279 : schedule_(schedule), inferrer_(inferrer), is_stub_(is_stub) {} | 279 const char* name) |
| 280 : schedule_(schedule), |
| 281 inferrer_(inferrer), |
| 282 is_stub_(is_stub), |
| 283 name_(name) {} |
| 280 | 284 |
| 281 void Run() { | 285 void Run() { |
| 282 BasicBlockVector const* blocks = schedule_->all_blocks(); | 286 BasicBlockVector const* blocks = schedule_->all_blocks(); |
| 283 for (BasicBlock* block : *blocks) { | 287 for (BasicBlock* block : *blocks) { |
| 284 for (size_t i = 0; i <= block->NodeCount(); ++i) { | 288 for (size_t i = 0; i <= block->NodeCount(); ++i) { |
| 285 Node const* node = | 289 Node const* node = |
| 286 i < block->NodeCount() ? block->NodeAt(i) : block->control_input(); | 290 i < block->NodeCount() ? block->NodeAt(i) : block->control_input(); |
| 287 if (node == nullptr) { | 291 if (node == nullptr) { |
| 288 DCHECK_EQ(block->NodeCount(), i); | 292 DCHECK_EQ(block->NodeCount(), i); |
| 289 break; | 293 break; |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 break; | 517 break; |
| 514 } | 518 } |
| 515 case IrOpcode::kTypedStateValues: | 519 case IrOpcode::kTypedStateValues: |
| 516 case IrOpcode::kFrameState: | 520 case IrOpcode::kFrameState: |
| 517 break; | 521 break; |
| 518 default: | 522 default: |
| 519 if (node->op()->ValueInputCount() != 0) { | 523 if (node->op()->ValueInputCount() != 0) { |
| 520 std::stringstream str; | 524 std::stringstream str; |
| 521 str << "Node #" << node->id() << ":" << *node->op() | 525 str << "Node #" << node->id() << ":" << *node->op() |
| 522 << " in the machine graph is not being checked."; | 526 << " in the machine graph is not being checked."; |
| 527 PrintDebugHelp(str, node); |
| 523 FATAL(str.str().c_str()); | 528 FATAL(str.str().c_str()); |
| 524 } | 529 } |
| 525 break; | 530 break; |
| 526 } | 531 } |
| 527 } | 532 } |
| 528 } | 533 } |
| 529 } | 534 } |
| 530 | 535 |
| 531 private: | 536 private: |
| 532 static bool Is32() { | 537 static bool Is32() { |
| 533 return MachineType::PointerRepresentation() == | 538 return MachineType::PointerRepresentation() == |
| 534 MachineRepresentation::kWord32; | 539 MachineRepresentation::kWord32; |
| 535 } | 540 } |
| 536 static bool Is64() { | 541 static bool Is64() { |
| 537 return MachineType::PointerRepresentation() == | 542 return MachineType::PointerRepresentation() == |
| 538 MachineRepresentation::kWord64; | 543 MachineRepresentation::kWord64; |
| 539 } | 544 } |
| 540 | 545 |
| 541 void CheckValueInputRepresentationIs(Node const* node, int index, | 546 void CheckValueInputRepresentationIs(Node const* node, int index, |
| 542 MachineRepresentation representation) { | 547 MachineRepresentation representation) { |
| 543 Node const* input = node->InputAt(index); | 548 Node const* input = node->InputAt(index); |
| 544 MachineRepresentation input_representation = | 549 MachineRepresentation input_representation = |
| 545 inferrer_->GetRepresentation(input); | 550 inferrer_->GetRepresentation(input); |
| 546 if (input_representation != representation) { | 551 if (input_representation != representation) { |
| 547 std::stringstream str; | 552 std::stringstream str; |
| 548 str << "TypeError: node #" << node->id() << ":" << *node->op() | 553 str << "TypeError: node #" << node->id() << ":" << *node->op() |
| 549 << " uses node #" << input->id() << ":" << *input->op() << ":" | 554 << " uses node #" << input->id() << ":" << *input->op() << ":" |
| 550 << input_representation << " which doesn't have a " << representation | 555 << input_representation << " which doesn't have a " << representation |
| 551 << " representation."; | 556 << " representation."; |
| 557 PrintDebugHelp(str, node); |
| 552 FATAL(str.str().c_str()); | 558 FATAL(str.str().c_str()); |
| 553 } | 559 } |
| 554 } | 560 } |
| 555 | 561 |
| 556 void CheckValueInputIsTagged(Node const* node, int index) { | 562 void CheckValueInputIsTagged(Node const* node, int index) { |
| 557 Node const* input = node->InputAt(index); | 563 Node const* input = node->InputAt(index); |
| 558 switch (inferrer_->GetRepresentation(input)) { | 564 switch (inferrer_->GetRepresentation(input)) { |
| 559 case MachineRepresentation::kTagged: | 565 case MachineRepresentation::kTagged: |
| 560 case MachineRepresentation::kTaggedPointer: | 566 case MachineRepresentation::kTaggedPointer: |
| 561 case MachineRepresentation::kTaggedSigned: | 567 case MachineRepresentation::kTaggedSigned: |
| 562 return; | 568 return; |
| 563 default: | 569 default: |
| 564 break; | 570 break; |
| 565 } | 571 } |
| 566 std::ostringstream str; | 572 std::ostringstream str; |
| 567 str << "TypeError: node #" << node->id() << ":" << *node->op() | 573 str << "TypeError: node #" << node->id() << ":" << *node->op() |
| 568 << " uses node #" << input->id() << ":" << *input->op() | 574 << " uses node #" << input->id() << ":" << *input->op() |
| 569 << " which doesn't have a tagged representation."; | 575 << " which doesn't have a tagged representation."; |
| 576 PrintDebugHelp(str, node); |
| 570 FATAL(str.str().c_str()); | 577 FATAL(str.str().c_str()); |
| 571 } | 578 } |
| 572 | 579 |
| 573 void CheckValueInputIsTaggedOrPointer(Node const* node, int index) { | 580 void CheckValueInputIsTaggedOrPointer(Node const* node, int index) { |
| 574 Node const* input = node->InputAt(index); | 581 Node const* input = node->InputAt(index); |
| 575 switch (inferrer_->GetRepresentation(input)) { | 582 switch (inferrer_->GetRepresentation(input)) { |
| 576 case MachineRepresentation::kTagged: | 583 case MachineRepresentation::kTagged: |
| 577 case MachineRepresentation::kTaggedPointer: | 584 case MachineRepresentation::kTaggedPointer: |
| 578 case MachineRepresentation::kTaggedSigned: | 585 case MachineRepresentation::kTaggedSigned: |
| 579 return; | 586 return; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 592 break; | 599 break; |
| 593 default: | 600 default: |
| 594 break; | 601 break; |
| 595 } | 602 } |
| 596 if (inferrer_->GetRepresentation(input) != | 603 if (inferrer_->GetRepresentation(input) != |
| 597 MachineType::PointerRepresentation()) { | 604 MachineType::PointerRepresentation()) { |
| 598 std::ostringstream str; | 605 std::ostringstream str; |
| 599 str << "TypeError: node #" << node->id() << ":" << *node->op() | 606 str << "TypeError: node #" << node->id() << ":" << *node->op() |
| 600 << " uses node #" << input->id() << ":" << *input->op() | 607 << " uses node #" << input->id() << ":" << *input->op() |
| 601 << " which doesn't have a tagged or pointer representation."; | 608 << " which doesn't have a tagged or pointer representation."; |
| 609 PrintDebugHelp(str, node); |
| 602 FATAL(str.str().c_str()); | 610 FATAL(str.str().c_str()); |
| 603 } | 611 } |
| 604 } | 612 } |
| 605 | 613 |
| 606 void CheckValueInputForInt32Op(Node const* node, int index) { | 614 void CheckValueInputForInt32Op(Node const* node, int index) { |
| 607 Node const* input = node->InputAt(index); | 615 Node const* input = node->InputAt(index); |
| 608 switch (inferrer_->GetRepresentation(input)) { | 616 switch (inferrer_->GetRepresentation(input)) { |
| 609 case MachineRepresentation::kBit: | 617 case MachineRepresentation::kBit: |
| 610 case MachineRepresentation::kWord8: | 618 case MachineRepresentation::kWord8: |
| 611 case MachineRepresentation::kWord16: | 619 case MachineRepresentation::kWord16: |
| 612 case MachineRepresentation::kWord32: | 620 case MachineRepresentation::kWord32: |
| 613 return; | 621 return; |
| 614 case MachineRepresentation::kNone: { | 622 case MachineRepresentation::kNone: { |
| 615 std::ostringstream str; | 623 std::ostringstream str; |
| 616 str << "TypeError: node #" << input->id() << ":" << *input->op() | 624 str << "TypeError: node #" << input->id() << ":" << *input->op() |
| 617 << " is untyped."; | 625 << " is untyped."; |
| 626 PrintDebugHelp(str, node); |
| 618 FATAL(str.str().c_str()); | 627 FATAL(str.str().c_str()); |
| 619 break; | 628 break; |
| 620 } | 629 } |
| 621 default: | 630 default: |
| 622 break; | 631 break; |
| 623 } | 632 } |
| 624 std::ostringstream str; | 633 std::ostringstream str; |
| 625 str << "TypeError: node #" << node->id() << ":" << *node->op() | 634 str << "TypeError: node #" << node->id() << ":" << *node->op() |
| 626 << " uses node #" << input->id() << ":" << *input->op() | 635 << " uses node #" << input->id() << ":" << *input->op() |
| 627 << " which doesn't have an int32-compatible representation."; | 636 << " which doesn't have an int32-compatible representation."; |
| 637 PrintDebugHelp(str, node); |
| 628 FATAL(str.str().c_str()); | 638 FATAL(str.str().c_str()); |
| 629 } | 639 } |
| 630 | 640 |
| 631 void CheckValueInputForInt64Op(Node const* node, int index) { | 641 void CheckValueInputForInt64Op(Node const* node, int index) { |
| 632 Node const* input = node->InputAt(index); | 642 Node const* input = node->InputAt(index); |
| 633 MachineRepresentation input_representation = | 643 MachineRepresentation input_representation = |
| 634 inferrer_->GetRepresentation(input); | 644 inferrer_->GetRepresentation(input); |
| 635 switch (input_representation) { | 645 switch (input_representation) { |
| 636 case MachineRepresentation::kWord64: | 646 case MachineRepresentation::kWord64: |
| 637 return; | 647 return; |
| 638 case MachineRepresentation::kNone: { | 648 case MachineRepresentation::kNone: { |
| 639 std::ostringstream str; | 649 std::ostringstream str; |
| 640 str << "TypeError: node #" << input->id() << ":" << *input->op() | 650 str << "TypeError: node #" << input->id() << ":" << *input->op() |
| 641 << " is untyped."; | 651 << " is untyped."; |
| 652 PrintDebugHelp(str, node); |
| 642 FATAL(str.str().c_str()); | 653 FATAL(str.str().c_str()); |
| 643 break; | 654 break; |
| 644 } | 655 } |
| 645 | 656 |
| 646 default: | 657 default: |
| 647 break; | 658 break; |
| 648 } | 659 } |
| 649 std::ostringstream str; | 660 std::ostringstream str; |
| 650 str << "TypeError: node #" << node->id() << ":" << *node->op() | 661 str << "TypeError: node #" << node->id() << ":" << *node->op() |
| 651 << " uses node #" << input->id() << ":" << *input->op() << ":" | 662 << " uses node #" << input->id() << ":" << *input->op() << ":" |
| 652 << input_representation | 663 << input_representation |
| 653 << " which doesn't have a kWord64 representation."; | 664 << " which doesn't have a kWord64 representation."; |
| 665 PrintDebugHelp(str, node); |
| 654 FATAL(str.str().c_str()); | 666 FATAL(str.str().c_str()); |
| 655 } | 667 } |
| 656 | 668 |
| 657 void CheckValueInputForFloat32Op(Node const* node, int index) { | 669 void CheckValueInputForFloat32Op(Node const* node, int index) { |
| 658 Node const* input = node->InputAt(index); | 670 Node const* input = node->InputAt(index); |
| 659 if (MachineRepresentation::kFloat32 == | 671 if (MachineRepresentation::kFloat32 == |
| 660 inferrer_->GetRepresentation(input)) { | 672 inferrer_->GetRepresentation(input)) { |
| 661 return; | 673 return; |
| 662 } | 674 } |
| 663 std::ostringstream str; | 675 std::ostringstream str; |
| 664 str << "TypeError: node #" << node->id() << ":" << *node->op() | 676 str << "TypeError: node #" << node->id() << ":" << *node->op() |
| 665 << " uses node #" << input->id() << ":" << *input->op() | 677 << " uses node #" << input->id() << ":" << *input->op() |
| 666 << " which doesn't have a kFloat32 representation."; | 678 << " which doesn't have a kFloat32 representation."; |
| 679 PrintDebugHelp(str, node); |
| 667 FATAL(str.str().c_str()); | 680 FATAL(str.str().c_str()); |
| 668 } | 681 } |
| 669 | 682 |
| 670 void CheckValueInputForFloat64Op(Node const* node, int index) { | 683 void CheckValueInputForFloat64Op(Node const* node, int index) { |
| 671 Node const* input = node->InputAt(index); | 684 Node const* input = node->InputAt(index); |
| 672 if (MachineRepresentation::kFloat64 == | 685 if (MachineRepresentation::kFloat64 == |
| 673 inferrer_->GetRepresentation(input)) { | 686 inferrer_->GetRepresentation(input)) { |
| 674 return; | 687 return; |
| 675 } | 688 } |
| 676 std::ostringstream str; | 689 std::ostringstream str; |
| 677 str << "TypeError: node #" << node->id() << ":" << *node->op() | 690 str << "TypeError: node #" << node->id() << ":" << *node->op() |
| 678 << " uses node #" << input->id() << ":" << *input->op() | 691 << " uses node #" << input->id() << ":" << *input->op() |
| 679 << " which doesn't have a kFloat64 representation."; | 692 << " which doesn't have a kFloat64 representation."; |
| 693 PrintDebugHelp(str, node); |
| 680 FATAL(str.str().c_str()); | 694 FATAL(str.str().c_str()); |
| 681 } | 695 } |
| 682 | 696 |
| 683 void CheckCallInputs(Node const* node) { | 697 void CheckCallInputs(Node const* node) { |
| 684 CallDescriptor const* desc = CallDescriptorOf(node->op()); | 698 CallDescriptor const* desc = CallDescriptorOf(node->op()); |
| 685 std::ostringstream str; | 699 std::ostringstream str; |
| 686 bool should_log_error = false; | 700 bool should_log_error = false; |
| 687 for (size_t i = 0; i < desc->InputCount(); ++i) { | 701 for (size_t i = 0; i < desc->InputCount(); ++i) { |
| 688 Node const* input = node->InputAt(static_cast<int>(i)); | 702 Node const* input = node->InputAt(static_cast<int>(i)); |
| 689 MachineRepresentation const input_type = | 703 MachineRepresentation const input_type = |
| 690 inferrer_->GetRepresentation(input); | 704 inferrer_->GetRepresentation(input); |
| 691 MachineRepresentation const expected_input_type = | 705 MachineRepresentation const expected_input_type = |
| 692 desc->GetInputType(i).representation(); | 706 desc->GetInputType(i).representation(); |
| 693 if (!IsCompatible(expected_input_type, input_type)) { | 707 if (!IsCompatible(expected_input_type, input_type)) { |
| 694 if (!should_log_error) { | 708 if (!should_log_error) { |
| 695 should_log_error = true; | 709 should_log_error = true; |
| 696 str << "TypeError: node #" << node->id() << ":" << *node->op() | 710 str << "TypeError: node #" << node->id() << ":" << *node->op() |
| 697 << " has wrong type for:" << std::endl; | 711 << " has wrong type for:" << std::endl; |
| 698 } else { | 712 } else { |
| 699 str << std::endl; | 713 str << std::endl; |
| 700 } | 714 } |
| 701 str << " * input " << i << " (" << input->id() << ":" << *input->op() | 715 str << " * input " << i << " (" << input->id() << ":" << *input->op() |
| 702 << ") doesn't have a " << expected_input_type << " representation."; | 716 << ") doesn't have a " << expected_input_type << " representation."; |
| 703 } | 717 } |
| 704 } | 718 } |
| 705 if (should_log_error) { | 719 if (should_log_error) { |
| 720 PrintDebugHelp(str, node); |
| 706 FATAL(str.str().c_str()); | 721 FATAL(str.str().c_str()); |
| 707 } | 722 } |
| 708 } | 723 } |
| 709 | 724 |
| 710 bool Intersect(MachineRepresentation lhs, MachineRepresentation rhs) { | 725 bool Intersect(MachineRepresentation lhs, MachineRepresentation rhs) { |
| 711 return (GetRepresentationProperties(lhs) & | 726 return (GetRepresentationProperties(lhs) & |
| 712 GetRepresentationProperties(rhs)) != 0; | 727 GetRepresentationProperties(rhs)) != 0; |
| 713 } | 728 } |
| 714 | 729 |
| 715 enum RepresentationProperties { kIsPointer = 1, kIsTagged = 2 }; | 730 enum RepresentationProperties { kIsPointer = 1, kIsTagged = 2 }; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 return (actual == MachineRepresentation::kBit || | 773 return (actual == MachineRepresentation::kBit || |
| 759 actual == MachineRepresentation::kWord8 || | 774 actual == MachineRepresentation::kWord8 || |
| 760 actual == MachineRepresentation::kWord16 || | 775 actual == MachineRepresentation::kWord16 || |
| 761 actual == MachineRepresentation::kWord32); | 776 actual == MachineRepresentation::kWord32); |
| 762 case MachineRepresentation::kNone: | 777 case MachineRepresentation::kNone: |
| 763 UNREACHABLE(); | 778 UNREACHABLE(); |
| 764 } | 779 } |
| 765 return false; | 780 return false; |
| 766 } | 781 } |
| 767 | 782 |
| 783 void PrintDebugHelp(std::ostream& out, Node const* node) { |
| 784 if (DEBUG_BOOL) { |
| 785 out << "\n#\n# Specify option --csa-trap-on-node=" << name_ << "," |
| 786 << node->id() << " for debugging."; |
| 787 } |
| 788 } |
| 789 |
| 768 Schedule const* const schedule_; | 790 Schedule const* const schedule_; |
| 769 MachineRepresentationInferrer const* const inferrer_; | 791 MachineRepresentationInferrer const* const inferrer_; |
| 770 bool is_stub_; | 792 bool is_stub_; |
| 793 const char* name_; |
| 771 }; | 794 }; |
| 772 | 795 |
| 773 } // namespace | 796 } // namespace |
| 774 | 797 |
| 775 void MachineGraphVerifier::Run(Graph* graph, Schedule const* const schedule, | 798 void MachineGraphVerifier::Run(Graph* graph, Schedule const* const schedule, |
| 776 Linkage* linkage, bool is_stub, | 799 Linkage* linkage, bool is_stub, const char* name, |
| 777 Zone* temp_zone) { | 800 Zone* temp_zone) { |
| 778 MachineRepresentationInferrer representation_inferrer(schedule, graph, | 801 MachineRepresentationInferrer representation_inferrer(schedule, graph, |
| 779 linkage, temp_zone); | 802 linkage, temp_zone); |
| 780 MachineRepresentationChecker checker(schedule, &representation_inferrer, | 803 MachineRepresentationChecker checker(schedule, &representation_inferrer, |
| 781 is_stub); | 804 is_stub, name); |
| 782 checker.Run(); | 805 checker.Run(); |
| 783 } | 806 } |
| 784 | 807 |
| 785 } // namespace compiler | 808 } // namespace compiler |
| 786 } // namespace internal | 809 } // namespace internal |
| 787 } // namespace v8 | 810 } // namespace v8 |
| OLD | NEW |