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 |