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:
MachineRepresentationInferrer(Schedule const * schedule,Graph const * graph,Linkage * linkage,Zone * zone)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 
GetRepresentation(Node const * node) const33   MachineRepresentation GetRepresentation(Node const* node) const {
34     return representation_vector_.at(node->id());
35   }
36 
37  private:
GetProjectionType(Node const * projection)38   MachineRepresentation GetProjectionType(Node const* projection) {
39     size_t index = ProjectionIndexOf(projection->op());
40     Node* input = projection->InputAt(0);
41     switch (input->opcode()) {
42       case IrOpcode::kInt32AddWithOverflow:
43       case IrOpcode::kInt32SubWithOverflow:
44       case IrOpcode::kInt32MulWithOverflow:
45         CHECK_LE(index, static_cast<size_t>(1));
46         return index == 0 ? MachineRepresentation::kWord32
47                           : MachineRepresentation::kBit;
48       case IrOpcode::kInt64AddWithOverflow:
49       case IrOpcode::kInt64SubWithOverflow:
50         CHECK_LE(index, static_cast<size_t>(1));
51         return index == 0 ? MachineRepresentation::kWord64
52                           : MachineRepresentation::kBit;
53       case IrOpcode::kTryTruncateFloat32ToInt64:
54       case IrOpcode::kTryTruncateFloat64ToInt64:
55       case IrOpcode::kTryTruncateFloat32ToUint64:
56       case IrOpcode::kTryTruncateFloat64ToUint64:
57         CHECK_LE(index, static_cast<size_t>(1));
58         return index == 0 ? MachineRepresentation::kWord64
59                           : MachineRepresentation::kBit;
60       case IrOpcode::kCall: {
61         CallDescriptor const* desc = CallDescriptorOf(input->op());
62         return desc->GetReturnType(index).representation();
63       }
64       default:
65         return MachineRepresentation::kNone;
66     }
67   }
68 
Run()69   void Run() {
70     auto blocks = schedule_->all_blocks();
71     for (BasicBlock* block : *blocks) {
72       for (size_t i = 0; i <= block->NodeCount(); ++i) {
73         Node const* node =
74             i < block->NodeCount() ? block->NodeAt(i) : block->control_input();
75         if (node == nullptr) {
76           DCHECK_EQ(block->NodeCount(), i);
77           break;
78         }
79         switch (node->opcode()) {
80           case IrOpcode::kParameter:
81             representation_vector_[node->id()] =
82                 linkage_->GetParameterType(ParameterIndexOf(node->op()))
83                     .representation();
84             break;
85           case IrOpcode::kProjection: {
86             representation_vector_[node->id()] = GetProjectionType(node);
87           } break;
88           case IrOpcode::kTypedStateValues:
89             representation_vector_[node->id()] = MachineRepresentation::kNone;
90             break;
91           case IrOpcode::kAtomicLoad:
92           case IrOpcode::kLoad:
93           case IrOpcode::kProtectedLoad:
94             representation_vector_[node->id()] =
95                 LoadRepresentationOf(node->op()).representation();
96             break;
97           case IrOpcode::kCheckedLoad:
98             representation_vector_[node->id()] =
99                 CheckedLoadRepresentationOf(node->op()).representation();
100             break;
101           case IrOpcode::kLoadStackPointer:
102           case IrOpcode::kLoadFramePointer:
103           case IrOpcode::kLoadParentFramePointer:
104             representation_vector_[node->id()] =
105                 MachineType::PointerRepresentation();
106             break;
107           case IrOpcode::kPhi:
108             representation_vector_[node->id()] =
109                 PhiRepresentationOf(node->op());
110             break;
111           case IrOpcode::kCall: {
112             CallDescriptor const* desc = CallDescriptorOf(node->op());
113             if (desc->ReturnCount() > 0) {
114               representation_vector_[node->id()] =
115                   desc->GetReturnType(0).representation();
116             } else {
117               representation_vector_[node->id()] =
118                   MachineRepresentation::kTagged;
119             }
120             break;
121           }
122           case IrOpcode::kUnalignedLoad:
123             representation_vector_[node->id()] =
124                 UnalignedLoadRepresentationOf(node->op()).representation();
125             break;
126           case IrOpcode::kHeapConstant:
127           case IrOpcode::kNumberConstant:
128           case IrOpcode::kChangeBitToTagged:
129           case IrOpcode::kIfException:
130           case IrOpcode::kOsrValue:
131           case IrOpcode::kChangeInt32ToTagged:
132           case IrOpcode::kChangeUint32ToTagged:
133           case IrOpcode::kBitcastWordToTagged:
134             representation_vector_[node->id()] = MachineRepresentation::kTagged;
135             break;
136           case IrOpcode::kExternalConstant:
137             representation_vector_[node->id()] =
138                 MachineType::PointerRepresentation();
139             break;
140           case IrOpcode::kBitcastTaggedToWord:
141             representation_vector_[node->id()] =
142                 MachineType::PointerRepresentation();
143             break;
144           case IrOpcode::kBitcastWordToTaggedSigned:
145             representation_vector_[node->id()] =
146                 MachineRepresentation::kTaggedSigned;
147             break;
148           case IrOpcode::kWord32Equal:
149           case IrOpcode::kInt32LessThan:
150           case IrOpcode::kInt32LessThanOrEqual:
151           case IrOpcode::kUint32LessThan:
152           case IrOpcode::kUint32LessThanOrEqual:
153           case IrOpcode::kWord64Equal:
154           case IrOpcode::kInt64LessThan:
155           case IrOpcode::kInt64LessThanOrEqual:
156           case IrOpcode::kUint64LessThan:
157           case IrOpcode::kUint64LessThanOrEqual:
158           case IrOpcode::kFloat32Equal:
159           case IrOpcode::kFloat32LessThan:
160           case IrOpcode::kFloat32LessThanOrEqual:
161           case IrOpcode::kFloat64Equal:
162           case IrOpcode::kFloat64LessThan:
163           case IrOpcode::kFloat64LessThanOrEqual:
164           case IrOpcode::kChangeTaggedToBit:
165             representation_vector_[node->id()] = MachineRepresentation::kBit;
166             break;
167 #define LABEL(opcode) case IrOpcode::k##opcode:
168           case IrOpcode::kTruncateInt64ToInt32:
169           case IrOpcode::kTruncateFloat32ToInt32:
170           case IrOpcode::kTruncateFloat32ToUint32:
171           case IrOpcode::kBitcastFloat32ToInt32:
172           case IrOpcode::kInt32x4ExtractLane:
173           case IrOpcode::kInt32Constant:
174           case IrOpcode::kRelocatableInt32Constant:
175           case IrOpcode::kTruncateFloat64ToWord32:
176           case IrOpcode::kTruncateFloat64ToUint32:
177           case IrOpcode::kChangeFloat64ToInt32:
178           case IrOpcode::kChangeFloat64ToUint32:
179           case IrOpcode::kRoundFloat64ToInt32:
180           case IrOpcode::kFloat64ExtractLowWord32:
181           case IrOpcode::kFloat64ExtractHighWord32:
182             MACHINE_UNOP_32_LIST(LABEL)
183             MACHINE_BINOP_32_LIST(LABEL) {
184               representation_vector_[node->id()] =
185                   MachineRepresentation::kWord32;
186             }
187             break;
188           case IrOpcode::kChangeInt32ToInt64:
189           case IrOpcode::kChangeUint32ToUint64:
190           case IrOpcode::kInt64Constant:
191           case IrOpcode::kRelocatableInt64Constant:
192           case IrOpcode::kBitcastFloat64ToInt64:
193             MACHINE_BINOP_64_LIST(LABEL) {
194               representation_vector_[node->id()] =
195                   MachineRepresentation::kWord64;
196             }
197             break;
198           case IrOpcode::kRoundInt32ToFloat32:
199           case IrOpcode::kRoundUint32ToFloat32:
200           case IrOpcode::kRoundInt64ToFloat32:
201           case IrOpcode::kRoundUint64ToFloat32:
202           case IrOpcode::kFloat32Constant:
203           case IrOpcode::kTruncateFloat64ToFloat32:
204             MACHINE_FLOAT32_BINOP_LIST(LABEL)
205             MACHINE_FLOAT32_UNOP_LIST(LABEL) {
206               representation_vector_[node->id()] =
207                   MachineRepresentation::kFloat32;
208             }
209             break;
210           case IrOpcode::kRoundInt64ToFloat64:
211           case IrOpcode::kRoundUint64ToFloat64:
212           case IrOpcode::kChangeFloat32ToFloat64:
213           case IrOpcode::kChangeInt32ToFloat64:
214           case IrOpcode::kChangeUint32ToFloat64:
215           case IrOpcode::kFloat64Constant:
216           case IrOpcode::kFloat64SilenceNaN:
217             MACHINE_FLOAT64_BINOP_LIST(LABEL)
218             MACHINE_FLOAT64_UNOP_LIST(LABEL) {
219               representation_vector_[node->id()] =
220                   MachineRepresentation::kFloat64;
221             }
222             break;
223 #undef LABEL
224           default:
225             break;
226         }
227       }
228     }
229   }
230 
231   Schedule const* const schedule_;
232   Linkage const* const linkage_;
233   ZoneVector<MachineRepresentation> representation_vector_;
234 };
235 
236 class MachineRepresentationChecker {
237  public:
MachineRepresentationChecker(Schedule const * const schedule,MachineRepresentationInferrer const * const inferrer)238   MachineRepresentationChecker(
239       Schedule const* const schedule,
240       MachineRepresentationInferrer const* const inferrer)
241       : schedule_(schedule), inferrer_(inferrer) {}
242 
Run()243   void Run() {
244     BasicBlockVector const* blocks = schedule_->all_blocks();
245     for (BasicBlock* block : *blocks) {
246       for (size_t i = 0; i <= block->NodeCount(); ++i) {
247         Node const* node =
248             i < block->NodeCount() ? block->NodeAt(i) : block->control_input();
249         if (node == nullptr) {
250           DCHECK_EQ(block->NodeCount(), i);
251           break;
252         }
253         switch (node->opcode()) {
254           case IrOpcode::kCall:
255           case IrOpcode::kTailCall:
256             CheckCallInputs(node);
257             break;
258           case IrOpcode::kChangeBitToTagged:
259             CHECK_EQ(MachineRepresentation::kBit,
260                      inferrer_->GetRepresentation(node->InputAt(0)));
261             break;
262           case IrOpcode::kChangeTaggedToBit:
263             CHECK_EQ(MachineRepresentation::kTagged,
264                      inferrer_->GetRepresentation(node->InputAt(0)));
265             break;
266           case IrOpcode::kRoundInt64ToFloat64:
267           case IrOpcode::kRoundUint64ToFloat64:
268           case IrOpcode::kRoundInt64ToFloat32:
269           case IrOpcode::kRoundUint64ToFloat32:
270           case IrOpcode::kTruncateInt64ToInt32:
271             CheckValueInputForInt64Op(node, 0);
272             break;
273           case IrOpcode::kBitcastWordToTagged:
274           case IrOpcode::kBitcastWordToTaggedSigned:
275             CheckValueInputRepresentationIs(
276                 node, 0, MachineType::PointerRepresentation());
277             break;
278           case IrOpcode::kBitcastTaggedToWord:
279             CheckValueInputIsTagged(node, 0);
280             break;
281           case IrOpcode::kTruncateFloat64ToWord32:
282           case IrOpcode::kTruncateFloat64ToUint32:
283           case IrOpcode::kTruncateFloat64ToFloat32:
284           case IrOpcode::kChangeFloat64ToInt32:
285           case IrOpcode::kChangeFloat64ToUint32:
286           case IrOpcode::kRoundFloat64ToInt32:
287           case IrOpcode::kFloat64ExtractLowWord32:
288           case IrOpcode::kFloat64ExtractHighWord32:
289           case IrOpcode::kBitcastFloat64ToInt64:
290             CheckValueInputForFloat64Op(node, 0);
291             break;
292           case IrOpcode::kWord64Equal:
293             CheckValueInputIsTaggedOrPointer(node, 0);
294             CheckValueInputRepresentationIs(
295                 node, 1, inferrer_->GetRepresentation(node->InputAt(0)));
296             break;
297           case IrOpcode::kInt64LessThan:
298           case IrOpcode::kInt64LessThanOrEqual:
299           case IrOpcode::kUint64LessThan:
300           case IrOpcode::kUint64LessThanOrEqual:
301             CheckValueInputForInt64Op(node, 0);
302             CheckValueInputForInt64Op(node, 1);
303             break;
304           case IrOpcode::kInt32x4ExtractLane:
305             CheckValueInputRepresentationIs(node, 0,
306                                             MachineRepresentation::kSimd128);
307             break;
308 #define LABEL(opcode) case IrOpcode::k##opcode:
309           case IrOpcode::kChangeInt32ToTagged:
310           case IrOpcode::kChangeUint32ToTagged:
311           case IrOpcode::kChangeInt32ToFloat64:
312           case IrOpcode::kChangeUint32ToFloat64:
313           case IrOpcode::kRoundInt32ToFloat32:
314           case IrOpcode::kRoundUint32ToFloat32:
315           case IrOpcode::kChangeInt32ToInt64:
316           case IrOpcode::kChangeUint32ToUint64:
317             MACHINE_UNOP_32_LIST(LABEL) { CheckValueInputForInt32Op(node, 0); }
318             break;
319           case IrOpcode::kWord32Equal:
320           case IrOpcode::kInt32LessThan:
321           case IrOpcode::kInt32LessThanOrEqual:
322           case IrOpcode::kUint32LessThan:
323           case IrOpcode::kUint32LessThanOrEqual:
324             MACHINE_BINOP_32_LIST(LABEL) {
325               CheckValueInputForInt32Op(node, 0);
326               CheckValueInputForInt32Op(node, 1);
327             }
328             break;
329             MACHINE_BINOP_64_LIST(LABEL) {
330               CheckValueInputForInt64Op(node, 0);
331               CheckValueInputForInt64Op(node, 1);
332             }
333             break;
334           case IrOpcode::kFloat32Equal:
335           case IrOpcode::kFloat32LessThan:
336           case IrOpcode::kFloat32LessThanOrEqual:
337             MACHINE_FLOAT32_BINOP_LIST(LABEL) {
338               CheckValueInputForFloat32Op(node, 0);
339               CheckValueInputForFloat32Op(node, 1);
340             }
341             break;
342           case IrOpcode::kChangeFloat32ToFloat64:
343           case IrOpcode::kTruncateFloat32ToInt32:
344           case IrOpcode::kTruncateFloat32ToUint32:
345           case IrOpcode::kBitcastFloat32ToInt32:
346             MACHINE_FLOAT32_UNOP_LIST(LABEL) {
347               CheckValueInputForFloat32Op(node, 0);
348             }
349             break;
350           case IrOpcode::kFloat64Equal:
351           case IrOpcode::kFloat64LessThan:
352           case IrOpcode::kFloat64LessThanOrEqual:
353             MACHINE_FLOAT64_BINOP_LIST(LABEL) {
354               CheckValueInputForFloat64Op(node, 0);
355               CheckValueInputForFloat64Op(node, 1);
356             }
357             break;
358           case IrOpcode::kFloat64SilenceNaN:
359             MACHINE_FLOAT64_UNOP_LIST(LABEL) {
360               CheckValueInputForFloat64Op(node, 0);
361             }
362             break;
363 #undef LABEL
364           case IrOpcode::kParameter:
365           case IrOpcode::kProjection:
366             break;
367           case IrOpcode::kLoad:
368           case IrOpcode::kAtomicLoad:
369             CheckValueInputIsTaggedOrPointer(node, 0);
370             CheckValueInputRepresentationIs(
371                 node, 1, MachineType::PointerRepresentation());
372             break;
373           case IrOpcode::kStore:
374             CheckValueInputIsTaggedOrPointer(node, 0);
375             CheckValueInputRepresentationIs(
376                 node, 1, MachineType::PointerRepresentation());
377             switch (StoreRepresentationOf(node->op()).representation()) {
378               case MachineRepresentation::kTagged:
379               case MachineRepresentation::kTaggedPointer:
380               case MachineRepresentation::kTaggedSigned:
381                 CheckValueInputIsTagged(node, 2);
382                 break;
383               default:
384                 CheckValueInputRepresentationIs(
385                     node, 2,
386                     StoreRepresentationOf(node->op()).representation());
387             }
388             break;
389           case IrOpcode::kAtomicStore:
390             CheckValueInputIsTaggedOrPointer(node, 0);
391             CheckValueInputRepresentationIs(
392                 node, 1, MachineType::PointerRepresentation());
393             switch (AtomicStoreRepresentationOf(node->op())) {
394               case MachineRepresentation::kTagged:
395               case MachineRepresentation::kTaggedPointer:
396               case MachineRepresentation::kTaggedSigned:
397                 CheckValueInputIsTagged(node, 2);
398                 break;
399               default:
400                 CheckValueInputRepresentationIs(
401                     node, 2, AtomicStoreRepresentationOf(node->op()));
402             }
403             break;
404           case IrOpcode::kPhi:
405             switch (inferrer_->GetRepresentation(node)) {
406               case MachineRepresentation::kTagged:
407               case MachineRepresentation::kTaggedPointer:
408               case MachineRepresentation::kTaggedSigned:
409                 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
410                   CheckValueInputIsTagged(node, i);
411                 }
412                 break;
413               default:
414                 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
415                   CheckValueInputRepresentationIs(
416                       node, i, inferrer_->GetRepresentation(node));
417                 }
418                 break;
419             }
420             break;
421           case IrOpcode::kBranch:
422           case IrOpcode::kSwitch:
423             CheckValueInputForInt32Op(node, 0);
424             break;
425           case IrOpcode::kReturn:
426             // TODO(epertoso): use the linkage to determine which tipe we
427             // should have here.
428             break;
429           case IrOpcode::kTypedStateValues:
430           case IrOpcode::kFrameState:
431             break;
432           default:
433             if (node->op()->ValueInputCount() != 0) {
434               std::stringstream str;
435               str << "Node #" << node->id() << ":" << *node->op()
436                   << " in the machine graph is not being checked.";
437               FATAL(str.str().c_str());
438             }
439             break;
440         }
441       }
442     }
443   }
444 
445  private:
CheckValueInputRepresentationIs(Node const * node,int index,MachineRepresentation representation)446   void CheckValueInputRepresentationIs(Node const* node, int index,
447                                        MachineRepresentation representation) {
448     Node const* input = node->InputAt(index);
449     MachineRepresentation input_representation =
450         inferrer_->GetRepresentation(input);
451     if (input_representation != representation) {
452       std::stringstream str;
453       str << "TypeError: node #" << node->id() << ":" << *node->op() << ":"
454           << MachineReprToString(input_representation) << " uses node #"
455           << input->id() << ":" << *input->op() << " which doesn't have a "
456           << MachineReprToString(representation) << " representation.";
457       FATAL(str.str().c_str());
458     }
459   }
460 
CheckValueInputIsTagged(Node const * node,int index)461   void CheckValueInputIsTagged(Node const* node, int index) {
462     Node const* input = node->InputAt(index);
463     switch (inferrer_->GetRepresentation(input)) {
464       case MachineRepresentation::kTagged:
465       case MachineRepresentation::kTaggedPointer:
466       case MachineRepresentation::kTaggedSigned:
467         return;
468       default:
469         break;
470     }
471     std::ostringstream str;
472     str << "TypeError: node #" << node->id() << ":" << *node->op()
473         << " uses node #" << input->id() << ":" << *input->op()
474         << " which doesn't have a tagged representation.";
475     FATAL(str.str().c_str());
476   }
477 
CheckValueInputIsTaggedOrPointer(Node const * node,int index)478   void CheckValueInputIsTaggedOrPointer(Node const* node, int index) {
479     Node const* input = node->InputAt(index);
480     switch (inferrer_->GetRepresentation(input)) {
481       case MachineRepresentation::kTagged:
482       case MachineRepresentation::kTaggedPointer:
483       case MachineRepresentation::kTaggedSigned:
484         return;
485       default:
486         break;
487     }
488     if (inferrer_->GetRepresentation(input) !=
489         MachineType::PointerRepresentation()) {
490       std::ostringstream str;
491       str << "TypeError: node #" << node->id() << ":" << *node->op()
492           << " uses node #" << input->id() << ":" << *input->op()
493           << " which doesn't have a tagged or pointer representation.";
494       FATAL(str.str().c_str());
495     }
496   }
497 
CheckValueInputForInt32Op(Node const * node,int index)498   void CheckValueInputForInt32Op(Node const* node, int index) {
499     Node const* input = node->InputAt(index);
500     switch (inferrer_->GetRepresentation(input)) {
501       case MachineRepresentation::kBit:
502       case MachineRepresentation::kWord8:
503       case MachineRepresentation::kWord16:
504       case MachineRepresentation::kWord32:
505         return;
506       case MachineRepresentation::kNone: {
507         std::ostringstream str;
508         str << "TypeError: node #" << input->id() << ":" << *input->op()
509             << " is untyped.";
510         FATAL(str.str().c_str());
511         break;
512       }
513       default:
514         break;
515     }
516     std::ostringstream str;
517     str << "TypeError: node #" << node->id() << ":" << *node->op()
518         << " uses node #" << input->id() << ":" << *input->op()
519         << " which doesn't have an int32-compatible representation.";
520     FATAL(str.str().c_str());
521   }
522 
CheckValueInputForInt64Op(Node const * node,int index)523   void CheckValueInputForInt64Op(Node const* node, int index) {
524     Node const* input = node->InputAt(index);
525     MachineRepresentation input_representation =
526         inferrer_->GetRepresentation(input);
527     switch (input_representation) {
528       case MachineRepresentation::kWord64:
529         return;
530       case MachineRepresentation::kNone: {
531         std::ostringstream str;
532         str << "TypeError: node #" << input->id() << ":" << *input->op()
533             << " is untyped.";
534         FATAL(str.str().c_str());
535         break;
536       }
537 
538       default:
539         break;
540     }
541     std::ostringstream str;
542     str << "TypeError: node #" << node->id() << ":" << *node->op() << ":"
543         << input_representation << " uses node #" << input->id() << ":"
544         << *input->op() << " which doesn't have a kWord64 representation.";
545     FATAL(str.str().c_str());
546   }
547 
CheckValueInputForFloat32Op(Node const * node,int index)548   void CheckValueInputForFloat32Op(Node const* node, int index) {
549     Node const* input = node->InputAt(index);
550     if (MachineRepresentation::kFloat32 ==
551         inferrer_->GetRepresentation(input)) {
552       return;
553     }
554     std::ostringstream str;
555     str << "TypeError: node #" << node->id() << ":" << *node->op()
556         << " uses node #" << input->id() << ":" << *input->op()
557         << " which doesn't have a kFloat32 representation.";
558     FATAL(str.str().c_str());
559   }
560 
CheckValueInputForFloat64Op(Node const * node,int index)561   void CheckValueInputForFloat64Op(Node const* node, int index) {
562     Node const* input = node->InputAt(index);
563     if (MachineRepresentation::kFloat64 ==
564         inferrer_->GetRepresentation(input)) {
565       return;
566     }
567     std::ostringstream str;
568     str << "TypeError: node #" << node->id() << ":" << *node->op()
569         << " uses node #" << input->id() << ":" << *input->op()
570         << " which doesn't have a kFloat64 representation.";
571     FATAL(str.str().c_str());
572   }
573 
CheckCallInputs(Node const * node)574   void CheckCallInputs(Node const* node) {
575     CallDescriptor const* desc = CallDescriptorOf(node->op());
576     std::ostringstream str;
577     bool should_log_error = false;
578     for (size_t i = 0; i < desc->InputCount(); ++i) {
579       Node const* input = node->InputAt(static_cast<int>(i));
580       MachineRepresentation const input_type =
581           inferrer_->GetRepresentation(input);
582       MachineRepresentation const expected_input_type =
583           desc->GetInputType(i).representation();
584       if (!IsCompatible(expected_input_type, input_type)) {
585         if (!should_log_error) {
586           should_log_error = true;
587           str << "TypeError: node #" << node->id() << ":" << *node->op()
588               << " has wrong type for:" << std::endl;
589         } else {
590           str << std::endl;
591         }
592         str << " * input " << i << " (" << input->id() << ":" << *input->op()
593             << ") doesn't have a " << MachineReprToString(expected_input_type)
594             << " representation.";
595       }
596     }
597     if (should_log_error) {
598       FATAL(str.str().c_str());
599     }
600   }
601 
Intersect(MachineRepresentation lhs,MachineRepresentation rhs)602   bool Intersect(MachineRepresentation lhs, MachineRepresentation rhs) {
603     return (GetRepresentationProperties(lhs) &
604             GetRepresentationProperties(rhs)) != 0;
605   }
606 
607   enum RepresentationProperties { kIsPointer = 1, kIsTagged = 2 };
608 
GetRepresentationProperties(MachineRepresentation representation)609   int GetRepresentationProperties(MachineRepresentation representation) {
610     switch (representation) {
611       case MachineRepresentation::kTagged:
612       case MachineRepresentation::kTaggedPointer:
613         return kIsPointer | kIsTagged;
614       case MachineRepresentation::kTaggedSigned:
615         return kIsTagged;
616       case MachineRepresentation::kWord32:
617         return MachineRepresentation::kWord32 ==
618                        MachineType::PointerRepresentation()
619                    ? kIsPointer
620                    : 0;
621       case MachineRepresentation::kWord64:
622         return MachineRepresentation::kWord64 ==
623                        MachineType::PointerRepresentation()
624                    ? kIsPointer
625                    : 0;
626       default:
627         return 0;
628     }
629   }
630 
IsCompatible(MachineRepresentation expected,MachineRepresentation actual)631   bool IsCompatible(MachineRepresentation expected,
632                     MachineRepresentation actual) {
633     switch (expected) {
634       case MachineRepresentation::kTagged:
635         return (actual == MachineRepresentation::kTagged ||
636                 actual == MachineRepresentation::kTaggedSigned ||
637                 actual == MachineRepresentation::kTaggedPointer);
638       case MachineRepresentation::kTaggedSigned:
639       case MachineRepresentation::kTaggedPointer:
640       case MachineRepresentation::kFloat32:
641       case MachineRepresentation::kFloat64:
642       case MachineRepresentation::kSimd128:
643       case MachineRepresentation::kBit:
644       case MachineRepresentation::kWord8:
645       case MachineRepresentation::kWord16:
646       case MachineRepresentation::kWord64:
647         return expected == actual;
648         break;
649       case MachineRepresentation::kWord32:
650         return (actual == MachineRepresentation::kBit ||
651                 actual == MachineRepresentation::kWord8 ||
652                 actual == MachineRepresentation::kWord16 ||
653                 actual == MachineRepresentation::kWord32);
654       case MachineRepresentation::kNone:
655         UNREACHABLE();
656     }
657     return false;
658   }
659 
660   Schedule const* const schedule_;
661   MachineRepresentationInferrer const* const inferrer_;
662 };
663 
664 }  // namespace
665 
Run(Graph * graph,Schedule const * const schedule,Linkage * linkage,Zone * temp_zone)666 void MachineGraphVerifier::Run(Graph* graph, Schedule const* const schedule,
667                                Linkage* linkage, Zone* temp_zone) {
668   MachineRepresentationInferrer representation_inferrer(schedule, graph,
669                                                         linkage, temp_zone);
670   MachineRepresentationChecker checker(schedule, &representation_inferrer);
671   checker.Run();
672 }
673 
674 }  // namespace compiler
675 }  // namespace internal
676 }  // namespace v8
677