Home | History | Annotate | Download | only in compiler
      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