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 3 // found in the LICENSE file. 4 5 #include "src/compiler/machine-graph-verifier.h" 6 7 #include "src/compiler/common-operator.h" 8 #include "src/compiler/graph.h" 9 #include "src/compiler/linkage.h" 10 #include "src/compiler/machine-operator.h" 11 #include "src/compiler/node-properties.h" 12 #include "src/compiler/node.h" 13 #include "src/compiler/schedule.h" 14 #include "src/zone/zone.h" 15 16 namespace v8 { 17 namespace internal { 18 namespace compiler { 19 20 namespace { 21 22 class MachineRepresentationInferrer { 23 public: 24 MachineRepresentationInferrer(Schedule const* schedule, Graph const* graph, 25 Linkage* linkage, Zone* zone) 26 : schedule_(schedule), 27 linkage_(linkage), 28 representation_vector_(graph->NodeCount(), MachineRepresentation::kNone, 29 zone) { 30 Run(); 31 } 32 33 CallDescriptor* call_descriptor() const { 34 return linkage_->GetIncomingDescriptor(); 35 } 36 37 MachineRepresentation GetRepresentation(Node const* node) const { 38 return representation_vector_.at(node->id()); 39 } 40 41 private: 42 MachineRepresentation GetProjectionType(Node const* projection) { 43 size_t index = ProjectionIndexOf(projection->op()); 44 Node* input = projection->InputAt(0); 45 switch (input->opcode()) { 46 case IrOpcode::kInt32AddWithOverflow: 47 case IrOpcode::kInt32SubWithOverflow: 48 case IrOpcode::kInt32MulWithOverflow: 49 CHECK_LE(index, static_cast<size_t>(1)); 50 return index == 0 ? MachineRepresentation::kWord32 51 : MachineRepresentation::kBit; 52 case IrOpcode::kInt64AddWithOverflow: 53 case IrOpcode::kInt64SubWithOverflow: 54 CHECK_LE(index, static_cast<size_t>(1)); 55 return index == 0 ? MachineRepresentation::kWord64 56 : MachineRepresentation::kBit; 57 case IrOpcode::kTryTruncateFloat32ToInt64: 58 case IrOpcode::kTryTruncateFloat64ToInt64: 59 case IrOpcode::kTryTruncateFloat32ToUint64: 60 case IrOpcode::kTryTruncateFloat64ToUint64: 61 CHECK_LE(index, static_cast<size_t>(1)); 62 return index == 0 ? MachineRepresentation::kWord64 63 : MachineRepresentation::kBit; 64 case IrOpcode::kCall: { 65 CallDescriptor const* desc = CallDescriptorOf(input->op()); 66 return desc->GetReturnType(index).representation(); 67 } 68 default: 69 return MachineRepresentation::kNone; 70 } 71 } 72 73 MachineRepresentation PromoteRepresentation(MachineRepresentation rep) { 74 switch (rep) { 75 case MachineRepresentation::kWord8: 76 case MachineRepresentation::kWord16: 77 case MachineRepresentation::kWord32: 78 return MachineRepresentation::kWord32; 79 default: 80 break; 81 } 82 return rep; 83 } 84 85 void Run() { 86 auto blocks = schedule_->all_blocks(); 87 for (BasicBlock* block : *blocks) { 88 for (size_t i = 0; i <= block->NodeCount(); ++i) { 89 Node const* node = 90 i < block->NodeCount() ? block->NodeAt(i) : block->control_input(); 91 if (node == nullptr) { 92 DCHECK_EQ(block->NodeCount(), i); 93 break; 94 } 95 switch (node->opcode()) { 96 case IrOpcode::kParameter: 97 representation_vector_[node->id()] = 98 linkage_->GetParameterType(ParameterIndexOf(node->op())) 99 .representation(); 100 break; 101 case IrOpcode::kReturn: { 102 representation_vector_[node->id()] = PromoteRepresentation( 103 linkage_->GetReturnType().representation()); 104 break; 105 } 106 case IrOpcode::kProjection: { 107 representation_vector_[node->id()] = GetProjectionType(node); 108 } break; 109 case IrOpcode::kTypedStateValues: 110 representation_vector_[node->id()] = MachineRepresentation::kNone; 111 break; 112 case IrOpcode::kAtomicLoad: 113 case IrOpcode::kLoad: 114 case IrOpcode::kProtectedLoad: 115 representation_vector_[node->id()] = PromoteRepresentation( 116 LoadRepresentationOf(node->op()).representation()); 117 break; 118 case IrOpcode::kCheckedLoad: 119 representation_vector_[node->id()] = PromoteRepresentation( 120 CheckedLoadRepresentationOf(node->op()).representation()); 121 break; 122 case IrOpcode::kLoadStackPointer: 123 case IrOpcode::kLoadFramePointer: 124 case IrOpcode::kLoadParentFramePointer: 125 representation_vector_[node->id()] = 126 MachineType::PointerRepresentation(); 127 break; 128 case IrOpcode::kUnalignedLoad: 129 representation_vector_[node->id()] = PromoteRepresentation( 130 UnalignedLoadRepresentationOf(node->op()).representation()); 131 break; 132 case IrOpcode::kPhi: 133 representation_vector_[node->id()] = 134 PhiRepresentationOf(node->op()); 135 break; 136 case IrOpcode::kCall: { 137 CallDescriptor const* desc = CallDescriptorOf(node->op()); 138 if (desc->ReturnCount() > 0) { 139 representation_vector_[node->id()] = 140 desc->GetReturnType(0).representation(); 141 } else { 142 representation_vector_[node->id()] = 143 MachineRepresentation::kTagged; 144 } 145 break; 146 } 147 case IrOpcode::kAtomicStore: 148 representation_vector_[node->id()] = 149 PromoteRepresentation(AtomicStoreRepresentationOf(node->op())); 150 break; 151 case IrOpcode::kStore: 152 case IrOpcode::kProtectedStore: 153 representation_vector_[node->id()] = PromoteRepresentation( 154 StoreRepresentationOf(node->op()).representation()); 155 break; 156 case IrOpcode::kCheckedStore: 157 representation_vector_[node->id()] = 158 PromoteRepresentation(CheckedStoreRepresentationOf(node->op())); 159 break; 160 case IrOpcode::kUnalignedStore: 161 representation_vector_[node->id()] = PromoteRepresentation( 162 UnalignedStoreRepresentationOf(node->op())); 163 break; 164 case IrOpcode::kHeapConstant: 165 case IrOpcode::kNumberConstant: 166 case IrOpcode::kChangeBitToTagged: 167 case IrOpcode::kIfException: 168 case IrOpcode::kOsrValue: 169 case IrOpcode::kChangeInt32ToTagged: 170 case IrOpcode::kChangeUint32ToTagged: 171 case IrOpcode::kBitcastWordToTagged: 172 representation_vector_[node->id()] = MachineRepresentation::kTagged; 173 break; 174 case IrOpcode::kExternalConstant: 175 representation_vector_[node->id()] = 176 MachineType::PointerRepresentation(); 177 break; 178 case IrOpcode::kBitcastTaggedToWord: 179 representation_vector_[node->id()] = 180 MachineType::PointerRepresentation(); 181 break; 182 case IrOpcode::kBitcastWordToTaggedSigned: 183 representation_vector_[node->id()] = 184 MachineRepresentation::kTaggedSigned; 185 break; 186 case IrOpcode::kWord32Equal: 187 case IrOpcode::kInt32LessThan: 188 case IrOpcode::kInt32LessThanOrEqual: 189 case IrOpcode::kUint32LessThan: 190 case IrOpcode::kUint32LessThanOrEqual: 191 case IrOpcode::kWord64Equal: 192 case IrOpcode::kInt64LessThan: 193 case IrOpcode::kInt64LessThanOrEqual: 194 case IrOpcode::kUint64LessThan: 195 case IrOpcode::kUint64LessThanOrEqual: 196 case IrOpcode::kFloat32Equal: 197 case IrOpcode::kFloat32LessThan: 198 case IrOpcode::kFloat32LessThanOrEqual: 199 case IrOpcode::kFloat64Equal: 200 case IrOpcode::kFloat64LessThan: 201 case IrOpcode::kFloat64LessThanOrEqual: 202 case IrOpcode::kChangeTaggedToBit: 203 representation_vector_[node->id()] = MachineRepresentation::kBit; 204 break; 205 #define LABEL(opcode) case IrOpcode::k##opcode: 206 case IrOpcode::kTruncateInt64ToInt32: 207 case IrOpcode::kTruncateFloat32ToInt32: 208 case IrOpcode::kTruncateFloat32ToUint32: 209 case IrOpcode::kBitcastFloat32ToInt32: 210 case IrOpcode::kInt32x4ExtractLane: 211 case IrOpcode::kInt16x8ExtractLane: 212 case IrOpcode::kInt8x16ExtractLane: 213 case IrOpcode::kInt32Constant: 214 case IrOpcode::kRelocatableInt32Constant: 215 case IrOpcode::kTruncateFloat64ToWord32: 216 case IrOpcode::kTruncateFloat64ToUint32: 217 case IrOpcode::kChangeFloat64ToInt32: 218 case IrOpcode::kChangeFloat64ToUint32: 219 case IrOpcode::kRoundFloat64ToInt32: 220 case IrOpcode::kFloat64ExtractLowWord32: 221 case IrOpcode::kFloat64ExtractHighWord32: 222 MACHINE_UNOP_32_LIST(LABEL) 223 MACHINE_BINOP_32_LIST(LABEL) { 224 representation_vector_[node->id()] = 225 MachineRepresentation::kWord32; 226 } 227 break; 228 case IrOpcode::kChangeInt32ToInt64: 229 case IrOpcode::kChangeUint32ToUint64: 230 case IrOpcode::kInt64Constant: 231 case IrOpcode::kRelocatableInt64Constant: 232 case IrOpcode::kBitcastFloat64ToInt64: 233 MACHINE_BINOP_64_LIST(LABEL) { 234 representation_vector_[node->id()] = 235 MachineRepresentation::kWord64; 236 } 237 break; 238 case IrOpcode::kRoundInt32ToFloat32: 239 case IrOpcode::kRoundUint32ToFloat32: 240 case IrOpcode::kRoundInt64ToFloat32: 241 case IrOpcode::kRoundUint64ToFloat32: 242 case IrOpcode::kFloat32Constant: 243 case IrOpcode::kTruncateFloat64ToFloat32: 244 MACHINE_FLOAT32_BINOP_LIST(LABEL) 245 MACHINE_FLOAT32_UNOP_LIST(LABEL) { 246 representation_vector_[node->id()] = 247 MachineRepresentation::kFloat32; 248 } 249 break; 250 case IrOpcode::kRoundInt64ToFloat64: 251 case IrOpcode::kRoundUint64ToFloat64: 252 case IrOpcode::kChangeFloat32ToFloat64: 253 case IrOpcode::kChangeInt32ToFloat64: 254 case IrOpcode::kChangeUint32ToFloat64: 255 case IrOpcode::kFloat64Constant: 256 case IrOpcode::kFloat64SilenceNaN: 257 MACHINE_FLOAT64_BINOP_LIST(LABEL) 258 MACHINE_FLOAT64_UNOP_LIST(LABEL) { 259 representation_vector_[node->id()] = 260 MachineRepresentation::kFloat64; 261 } 262 break; 263 #undef LABEL 264 default: 265 break; 266 } 267 } 268 } 269 } 270 271 Schedule const* const schedule_; 272 Linkage const* const linkage_; 273 ZoneVector<MachineRepresentation> representation_vector_; 274 }; 275 276 class MachineRepresentationChecker { 277 public: 278 MachineRepresentationChecker( 279 Schedule const* const schedule, 280 MachineRepresentationInferrer const* const inferrer, bool is_stub, 281 const char* name) 282 : schedule_(schedule), 283 inferrer_(inferrer), 284 is_stub_(is_stub), 285 name_(name) {} 286 287 void Run() { 288 BasicBlockVector const* blocks = schedule_->all_blocks(); 289 for (BasicBlock* block : *blocks) { 290 for (size_t i = 0; i <= block->NodeCount(); ++i) { 291 Node const* node = 292 i < block->NodeCount() ? block->NodeAt(i) : block->control_input(); 293 if (node == nullptr) { 294 DCHECK_EQ(block->NodeCount(), i); 295 break; 296 } 297 switch (node->opcode()) { 298 case IrOpcode::kCall: 299 case IrOpcode::kTailCall: 300 CheckCallInputs(node); 301 break; 302 case IrOpcode::kChangeBitToTagged: 303 CHECK_EQ(MachineRepresentation::kBit, 304 inferrer_->GetRepresentation(node->InputAt(0))); 305 break; 306 case IrOpcode::kChangeTaggedToBit: 307 CHECK_EQ(MachineRepresentation::kTagged, 308 inferrer_->GetRepresentation(node->InputAt(0))); 309 break; 310 case IrOpcode::kRoundInt64ToFloat64: 311 case IrOpcode::kRoundUint64ToFloat64: 312 case IrOpcode::kRoundInt64ToFloat32: 313 case IrOpcode::kRoundUint64ToFloat32: 314 case IrOpcode::kTruncateInt64ToInt32: 315 CheckValueInputForInt64Op(node, 0); 316 break; 317 case IrOpcode::kBitcastWordToTagged: 318 case IrOpcode::kBitcastWordToTaggedSigned: 319 CheckValueInputRepresentationIs( 320 node, 0, MachineType::PointerRepresentation()); 321 break; 322 case IrOpcode::kBitcastTaggedToWord: 323 CheckValueInputIsTagged(node, 0); 324 break; 325 case IrOpcode::kTruncateFloat64ToWord32: 326 case IrOpcode::kTruncateFloat64ToUint32: 327 case IrOpcode::kTruncateFloat64ToFloat32: 328 case IrOpcode::kChangeFloat64ToInt32: 329 case IrOpcode::kChangeFloat64ToUint32: 330 case IrOpcode::kRoundFloat64ToInt32: 331 case IrOpcode::kFloat64ExtractLowWord32: 332 case IrOpcode::kFloat64ExtractHighWord32: 333 case IrOpcode::kBitcastFloat64ToInt64: 334 CheckValueInputForFloat64Op(node, 0); 335 break; 336 case IrOpcode::kWord64Equal: 337 if (Is64()) { 338 CheckValueInputIsTaggedOrPointer(node, 0); 339 CheckValueInputIsTaggedOrPointer(node, 1); 340 if (!is_stub_) { 341 CheckValueInputRepresentationIs( 342 node, 1, inferrer_->GetRepresentation(node->InputAt(0))); 343 } 344 } else { 345 CheckValueInputForInt64Op(node, 0); 346 CheckValueInputForInt64Op(node, 1); 347 } 348 break; 349 case IrOpcode::kInt64LessThan: 350 case IrOpcode::kInt64LessThanOrEqual: 351 case IrOpcode::kUint64LessThan: 352 case IrOpcode::kUint64LessThanOrEqual: 353 CheckValueInputForInt64Op(node, 0); 354 CheckValueInputForInt64Op(node, 1); 355 break; 356 case IrOpcode::kInt32x4ExtractLane: 357 case IrOpcode::kInt16x8ExtractLane: 358 case IrOpcode::kInt8x16ExtractLane: 359 CheckValueInputRepresentationIs(node, 0, 360 MachineRepresentation::kSimd128); 361 break; 362 #define LABEL(opcode) case IrOpcode::k##opcode: 363 case IrOpcode::kChangeInt32ToTagged: 364 case IrOpcode::kChangeUint32ToTagged: 365 case IrOpcode::kChangeInt32ToFloat64: 366 case IrOpcode::kChangeUint32ToFloat64: 367 case IrOpcode::kRoundInt32ToFloat32: 368 case IrOpcode::kRoundUint32ToFloat32: 369 case IrOpcode::kChangeInt32ToInt64: 370 case IrOpcode::kChangeUint32ToUint64: 371 MACHINE_UNOP_32_LIST(LABEL) { CheckValueInputForInt32Op(node, 0); } 372 break; 373 case IrOpcode::kWord32Equal: 374 if (Is32()) { 375 CheckValueInputIsTaggedOrPointer(node, 0); 376 CheckValueInputIsTaggedOrPointer(node, 1); 377 if (!is_stub_) { 378 CheckValueInputRepresentationIs( 379 node, 1, inferrer_->GetRepresentation(node->InputAt(0))); 380 } 381 } else { 382 CheckValueInputForInt32Op(node, 0); 383 CheckValueInputForInt32Op(node, 1); 384 } 385 break; 386 387 case IrOpcode::kInt32LessThan: 388 case IrOpcode::kInt32LessThanOrEqual: 389 case IrOpcode::kUint32LessThan: 390 case IrOpcode::kUint32LessThanOrEqual: 391 MACHINE_BINOP_32_LIST(LABEL) { 392 CheckValueInputForInt32Op(node, 0); 393 CheckValueInputForInt32Op(node, 1); 394 } 395 break; 396 MACHINE_BINOP_64_LIST(LABEL) { 397 CheckValueInputForInt64Op(node, 0); 398 CheckValueInputForInt64Op(node, 1); 399 } 400 break; 401 case IrOpcode::kFloat32Equal: 402 case IrOpcode::kFloat32LessThan: 403 case IrOpcode::kFloat32LessThanOrEqual: 404 MACHINE_FLOAT32_BINOP_LIST(LABEL) { 405 CheckValueInputForFloat32Op(node, 0); 406 CheckValueInputForFloat32Op(node, 1); 407 } 408 break; 409 case IrOpcode::kChangeFloat32ToFloat64: 410 case IrOpcode::kTruncateFloat32ToInt32: 411 case IrOpcode::kTruncateFloat32ToUint32: 412 case IrOpcode::kBitcastFloat32ToInt32: 413 MACHINE_FLOAT32_UNOP_LIST(LABEL) { 414 CheckValueInputForFloat32Op(node, 0); 415 } 416 break; 417 case IrOpcode::kFloat64Equal: 418 case IrOpcode::kFloat64LessThan: 419 case IrOpcode::kFloat64LessThanOrEqual: 420 MACHINE_FLOAT64_BINOP_LIST(LABEL) { 421 CheckValueInputForFloat64Op(node, 0); 422 CheckValueInputForFloat64Op(node, 1); 423 } 424 break; 425 case IrOpcode::kFloat64SilenceNaN: 426 MACHINE_FLOAT64_UNOP_LIST(LABEL) { 427 CheckValueInputForFloat64Op(node, 0); 428 } 429 break; 430 #undef LABEL 431 case IrOpcode::kParameter: 432 case IrOpcode::kProjection: 433 break; 434 case IrOpcode::kLoad: 435 case IrOpcode::kAtomicLoad: 436 CheckValueInputIsTaggedOrPointer(node, 0); 437 CheckValueInputRepresentationIs( 438 node, 1, MachineType::PointerRepresentation()); 439 break; 440 case IrOpcode::kStore: 441 CheckValueInputIsTaggedOrPointer(node, 0); 442 CheckValueInputRepresentationIs( 443 node, 1, MachineType::PointerRepresentation()); 444 switch (inferrer_->GetRepresentation(node)) { 445 case MachineRepresentation::kTagged: 446 case MachineRepresentation::kTaggedPointer: 447 case MachineRepresentation::kTaggedSigned: 448 CheckValueInputIsTagged(node, 2); 449 break; 450 default: 451 CheckValueInputRepresentationIs( 452 node, 2, inferrer_->GetRepresentation(node)); 453 } 454 break; 455 case IrOpcode::kAtomicStore: 456 CheckValueInputIsTaggedOrPointer(node, 0); 457 CheckValueInputRepresentationIs( 458 node, 1, MachineType::PointerRepresentation()); 459 switch (inferrer_->GetRepresentation(node)) { 460 case MachineRepresentation::kTagged: 461 case MachineRepresentation::kTaggedPointer: 462 case MachineRepresentation::kTaggedSigned: 463 CheckValueInputIsTagged(node, 2); 464 break; 465 default: 466 CheckValueInputRepresentationIs( 467 node, 2, inferrer_->GetRepresentation(node)); 468 } 469 break; 470 case IrOpcode::kPhi: 471 switch (inferrer_->GetRepresentation(node)) { 472 case MachineRepresentation::kTagged: 473 case MachineRepresentation::kTaggedPointer: 474 case MachineRepresentation::kTaggedSigned: 475 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { 476 CheckValueInputIsTagged(node, i); 477 } 478 break; 479 case MachineRepresentation::kWord32: 480 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { 481 CheckValueInputForInt32Op(node, i); 482 } 483 break; 484 default: 485 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { 486 CheckValueInputRepresentationIs( 487 node, i, inferrer_->GetRepresentation(node)); 488 } 489 break; 490 } 491 break; 492 case IrOpcode::kBranch: 493 case IrOpcode::kSwitch: 494 CheckValueInputForInt32Op(node, 0); 495 break; 496 case IrOpcode::kReturn: { 497 // TODO(ishell): enable once the pop count parameter type becomes 498 // MachineType::PointerRepresentation(). Currently it's int32 or 499 // word-size. 500 // CheckValueInputRepresentationIs( 501 // node, 0, MachineType::PointerRepresentation()); // Pop count 502 size_t return_count = inferrer_->call_descriptor()->ReturnCount(); 503 for (size_t i = 0; i < return_count; i++) { 504 MachineType type = inferrer_->call_descriptor()->GetReturnType(i); 505 int input_index = static_cast<int>(i + 1); 506 switch (type.representation()) { 507 case MachineRepresentation::kTagged: 508 case MachineRepresentation::kTaggedPointer: 509 case MachineRepresentation::kTaggedSigned: 510 CheckValueInputIsTagged(node, input_index); 511 break; 512 case MachineRepresentation::kWord32: 513 CheckValueInputForInt32Op(node, input_index); 514 break; 515 default: 516 CheckValueInputRepresentationIs( 517 node, 2, inferrer_->GetRepresentation(node)); 518 } 519 break; 520 } 521 break; 522 } 523 case IrOpcode::kThrow: 524 CheckValueInputIsTagged(node, 0); 525 break; 526 case IrOpcode::kTypedStateValues: 527 case IrOpcode::kFrameState: 528 break; 529 default: 530 if (node->op()->ValueInputCount() != 0) { 531 std::stringstream str; 532 str << "Node #" << node->id() << ":" << *node->op() 533 << " in the machine graph is not being checked."; 534 PrintDebugHelp(str, node); 535 FATAL(str.str().c_str()); 536 } 537 break; 538 } 539 } 540 } 541 } 542 543 private: 544 static bool Is32() { 545 return MachineType::PointerRepresentation() == 546 MachineRepresentation::kWord32; 547 } 548 static bool Is64() { 549 return MachineType::PointerRepresentation() == 550 MachineRepresentation::kWord64; 551 } 552 553 void CheckValueInputRepresentationIs(Node const* node, int index, 554 MachineRepresentation representation) { 555 Node const* input = node->InputAt(index); 556 MachineRepresentation input_representation = 557 inferrer_->GetRepresentation(input); 558 if (input_representation != representation) { 559 std::stringstream str; 560 str << "TypeError: node #" << node->id() << ":" << *node->op() 561 << " uses node #" << input->id() << ":" << *input->op() << ":" 562 << input_representation << " which doesn't have a " << representation 563 << " representation."; 564 PrintDebugHelp(str, node); 565 FATAL(str.str().c_str()); 566 } 567 } 568 569 void CheckValueInputIsTagged(Node const* node, int index) { 570 Node const* input = node->InputAt(index); 571 switch (inferrer_->GetRepresentation(input)) { 572 case MachineRepresentation::kTagged: 573 case MachineRepresentation::kTaggedPointer: 574 case MachineRepresentation::kTaggedSigned: 575 return; 576 default: 577 break; 578 } 579 std::ostringstream str; 580 str << "TypeError: node #" << node->id() << ":" << *node->op() 581 << " uses node #" << input->id() << ":" << *input->op() 582 << " which doesn't have a tagged representation."; 583 PrintDebugHelp(str, node); 584 FATAL(str.str().c_str()); 585 } 586 587 void CheckValueInputIsTaggedOrPointer(Node const* node, int index) { 588 Node const* input = node->InputAt(index); 589 switch (inferrer_->GetRepresentation(input)) { 590 case MachineRepresentation::kTagged: 591 case MachineRepresentation::kTaggedPointer: 592 case MachineRepresentation::kTaggedSigned: 593 return; 594 case MachineRepresentation::kBit: 595 case MachineRepresentation::kWord8: 596 case MachineRepresentation::kWord16: 597 case MachineRepresentation::kWord32: 598 if (Is32()) { 599 return; 600 } 601 break; 602 case MachineRepresentation::kWord64: 603 if (Is64()) { 604 return; 605 } 606 break; 607 default: 608 break; 609 } 610 if (inferrer_->GetRepresentation(input) != 611 MachineType::PointerRepresentation()) { 612 std::ostringstream str; 613 str << "TypeError: node #" << node->id() << ":" << *node->op() 614 << " uses node #" << input->id() << ":" << *input->op() 615 << " which doesn't have a tagged or pointer representation."; 616 PrintDebugHelp(str, node); 617 FATAL(str.str().c_str()); 618 } 619 } 620 621 void CheckValueInputForInt32Op(Node const* node, int index) { 622 Node const* input = node->InputAt(index); 623 switch (inferrer_->GetRepresentation(input)) { 624 case MachineRepresentation::kBit: 625 case MachineRepresentation::kWord8: 626 case MachineRepresentation::kWord16: 627 case MachineRepresentation::kWord32: 628 return; 629 case MachineRepresentation::kNone: { 630 std::ostringstream str; 631 str << "TypeError: node #" << input->id() << ":" << *input->op() 632 << " is untyped."; 633 PrintDebugHelp(str, node); 634 FATAL(str.str().c_str()); 635 break; 636 } 637 default: 638 break; 639 } 640 std::ostringstream str; 641 str << "TypeError: node #" << node->id() << ":" << *node->op() 642 << " uses node #" << input->id() << ":" << *input->op() 643 << " which doesn't have an int32-compatible representation."; 644 PrintDebugHelp(str, node); 645 FATAL(str.str().c_str()); 646 } 647 648 void CheckValueInputForInt64Op(Node const* node, int index) { 649 Node const* input = node->InputAt(index); 650 MachineRepresentation input_representation = 651 inferrer_->GetRepresentation(input); 652 switch (input_representation) { 653 case MachineRepresentation::kWord64: 654 return; 655 case MachineRepresentation::kNone: { 656 std::ostringstream str; 657 str << "TypeError: node #" << input->id() << ":" << *input->op() 658 << " is untyped."; 659 PrintDebugHelp(str, node); 660 FATAL(str.str().c_str()); 661 break; 662 } 663 664 default: 665 break; 666 } 667 std::ostringstream str; 668 str << "TypeError: node #" << node->id() << ":" << *node->op() 669 << " uses node #" << input->id() << ":" << *input->op() << ":" 670 << input_representation 671 << " which doesn't have a kWord64 representation."; 672 PrintDebugHelp(str, node); 673 FATAL(str.str().c_str()); 674 } 675 676 void CheckValueInputForFloat32Op(Node const* node, int index) { 677 Node const* input = node->InputAt(index); 678 if (MachineRepresentation::kFloat32 == 679 inferrer_->GetRepresentation(input)) { 680 return; 681 } 682 std::ostringstream str; 683 str << "TypeError: node #" << node->id() << ":" << *node->op() 684 << " uses node #" << input->id() << ":" << *input->op() 685 << " which doesn't have a kFloat32 representation."; 686 PrintDebugHelp(str, node); 687 FATAL(str.str().c_str()); 688 } 689 690 void CheckValueInputForFloat64Op(Node const* node, int index) { 691 Node const* input = node->InputAt(index); 692 if (MachineRepresentation::kFloat64 == 693 inferrer_->GetRepresentation(input)) { 694 return; 695 } 696 std::ostringstream str; 697 str << "TypeError: node #" << node->id() << ":" << *node->op() 698 << " uses node #" << input->id() << ":" << *input->op() 699 << " which doesn't have a kFloat64 representation."; 700 PrintDebugHelp(str, node); 701 FATAL(str.str().c_str()); 702 } 703 704 void CheckCallInputs(Node const* node) { 705 CallDescriptor const* desc = CallDescriptorOf(node->op()); 706 std::ostringstream str; 707 bool should_log_error = false; 708 for (size_t i = 0; i < desc->InputCount(); ++i) { 709 Node const* input = node->InputAt(static_cast<int>(i)); 710 MachineRepresentation const input_type = 711 inferrer_->GetRepresentation(input); 712 MachineRepresentation const expected_input_type = 713 desc->GetInputType(i).representation(); 714 if (!IsCompatible(expected_input_type, input_type)) { 715 if (!should_log_error) { 716 should_log_error = true; 717 str << "TypeError: node #" << node->id() << ":" << *node->op() 718 << " has wrong type for:" << std::endl; 719 } else { 720 str << std::endl; 721 } 722 str << " * input " << i << " (" << input->id() << ":" << *input->op() 723 << ") doesn't have a " << expected_input_type << " representation."; 724 } 725 } 726 if (should_log_error) { 727 PrintDebugHelp(str, node); 728 FATAL(str.str().c_str()); 729 } 730 } 731 732 bool Intersect(MachineRepresentation lhs, MachineRepresentation rhs) { 733 return (GetRepresentationProperties(lhs) & 734 GetRepresentationProperties(rhs)) != 0; 735 } 736 737 enum RepresentationProperties { kIsPointer = 1, kIsTagged = 2 }; 738 739 int GetRepresentationProperties(MachineRepresentation representation) { 740 switch (representation) { 741 case MachineRepresentation::kTagged: 742 case MachineRepresentation::kTaggedPointer: 743 return kIsPointer | kIsTagged; 744 case MachineRepresentation::kTaggedSigned: 745 return kIsTagged; 746 case MachineRepresentation::kWord32: 747 return MachineRepresentation::kWord32 == 748 MachineType::PointerRepresentation() 749 ? kIsPointer 750 : 0; 751 case MachineRepresentation::kWord64: 752 return MachineRepresentation::kWord64 == 753 MachineType::PointerRepresentation() 754 ? kIsPointer 755 : 0; 756 default: 757 return 0; 758 } 759 } 760 761 bool IsCompatible(MachineRepresentation expected, 762 MachineRepresentation actual) { 763 switch (expected) { 764 case MachineRepresentation::kTagged: 765 return (actual == MachineRepresentation::kTagged || 766 actual == MachineRepresentation::kTaggedSigned || 767 actual == MachineRepresentation::kTaggedPointer); 768 case MachineRepresentation::kTaggedSigned: 769 case MachineRepresentation::kTaggedPointer: 770 case MachineRepresentation::kFloat32: 771 case MachineRepresentation::kFloat64: 772 case MachineRepresentation::kSimd128: 773 case MachineRepresentation::kSimd1x4: 774 case MachineRepresentation::kSimd1x8: 775 case MachineRepresentation::kSimd1x16: 776 case MachineRepresentation::kBit: 777 case MachineRepresentation::kWord8: 778 case MachineRepresentation::kWord16: 779 case MachineRepresentation::kWord64: 780 return expected == actual; 781 break; 782 case MachineRepresentation::kWord32: 783 return (actual == MachineRepresentation::kBit || 784 actual == MachineRepresentation::kWord8 || 785 actual == MachineRepresentation::kWord16 || 786 actual == MachineRepresentation::kWord32); 787 case MachineRepresentation::kNone: 788 UNREACHABLE(); 789 } 790 return false; 791 } 792 793 void PrintDebugHelp(std::ostream& out, Node const* node) { 794 if (DEBUG_BOOL) { 795 out << "\n#\n# Specify option --csa-trap-on-node=" << name_ << "," 796 << node->id() << " for debugging."; 797 } 798 } 799 800 Schedule const* const schedule_; 801 MachineRepresentationInferrer const* const inferrer_; 802 bool is_stub_; 803 const char* name_; 804 }; 805 806 } // namespace 807 808 void MachineGraphVerifier::Run(Graph* graph, Schedule const* const schedule, 809 Linkage* linkage, bool is_stub, const char* name, 810 Zone* temp_zone) { 811 MachineRepresentationInferrer representation_inferrer(schedule, graph, 812 linkage, temp_zone); 813 MachineRepresentationChecker checker(schedule, &representation_inferrer, 814 is_stub, name); 815 checker.Run(); 816 } 817 818 } // namespace compiler 819 } // namespace internal 820 } // namespace v8 821