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 |