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 
call_descriptor() const33   CallDescriptor* call_descriptor() const {
34     return linkage_->GetIncomingDescriptor();
35   }
36 
GetRepresentation(Node const * node) const37   MachineRepresentation GetRepresentation(Node const* node) const {
38     return representation_vector_.at(node->id());
39   }
40 
41  private:
GetProjectionType(Node const * projection)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         CHECK_LE(index, static_cast<size_t>(1));
61         return index == 0 ? MachineRepresentation::kWord64
62                           : MachineRepresentation::kBit;
63       case IrOpcode::kCall: {
64         auto call_descriptor = CallDescriptorOf(input->op());
65         return call_descriptor->GetReturnType(index).representation();
66       }
67       case IrOpcode::kWord32AtomicPairLoad:
68       case IrOpcode::kWord32AtomicPairAdd:
69       case IrOpcode::kWord32AtomicPairSub:
70       case IrOpcode::kWord32AtomicPairAnd:
71       case IrOpcode::kWord32AtomicPairOr:
72       case IrOpcode::kWord32AtomicPairXor:
73       case IrOpcode::kWord32AtomicPairExchange:
74       case IrOpcode::kWord32AtomicPairCompareExchange:
75         CHECK_LE(index, static_cast<size_t>(1));
76         return MachineRepresentation::kWord32;
77       default:
78         return MachineRepresentation::kNone;
79     }
80   }
81 
PromoteRepresentation(MachineRepresentation rep)82   MachineRepresentation PromoteRepresentation(MachineRepresentation rep) {
83     switch (rep) {
84       case MachineRepresentation::kWord8:
85       case MachineRepresentation::kWord16:
86       case MachineRepresentation::kWord32:
87         return MachineRepresentation::kWord32;
88       default:
89         break;
90     }
91     return rep;
92   }
93 
Run()94   void Run() {
95     auto blocks = schedule_->all_blocks();
96     for (BasicBlock* block : *blocks) {
97       current_block_ = block;
98       for (size_t i = 0; i <= block->NodeCount(); ++i) {
99         Node const* node =
100             i < block->NodeCount() ? block->NodeAt(i) : block->control_input();
101         if (node == nullptr) {
102           DCHECK_EQ(block->NodeCount(), i);
103           break;
104         }
105         switch (node->opcode()) {
106           case IrOpcode::kParameter:
107             representation_vector_[node->id()] =
108                 linkage_->GetParameterType(ParameterIndexOf(node->op()))
109                     .representation();
110             break;
111           case IrOpcode::kReturn: {
112             representation_vector_[node->id()] = PromoteRepresentation(
113                 linkage_->GetReturnType().representation());
114             break;
115           }
116           case IrOpcode::kProjection: {
117             representation_vector_[node->id()] = GetProjectionType(node);
118           } break;
119           case IrOpcode::kTypedStateValues:
120             representation_vector_[node->id()] = MachineRepresentation::kNone;
121             break;
122           case IrOpcode::kWord32AtomicLoad:
123           case IrOpcode::kWord64AtomicLoad:
124           case IrOpcode::kLoad:
125           case IrOpcode::kProtectedLoad:
126           case IrOpcode::kPoisonedLoad:
127             representation_vector_[node->id()] = PromoteRepresentation(
128                 LoadRepresentationOf(node->op()).representation());
129             break;
130           case IrOpcode::kLoadFramePointer:
131           case IrOpcode::kLoadParentFramePointer:
132             representation_vector_[node->id()] =
133                 MachineType::PointerRepresentation();
134             break;
135           case IrOpcode::kUnalignedLoad:
136             representation_vector_[node->id()] = PromoteRepresentation(
137                 LoadRepresentationOf(node->op()).representation());
138             break;
139           case IrOpcode::kPhi:
140             representation_vector_[node->id()] =
141                 PhiRepresentationOf(node->op());
142             break;
143           case IrOpcode::kCall: {
144             auto call_descriptor = CallDescriptorOf(node->op());
145             if (call_descriptor->ReturnCount() > 0) {
146               representation_vector_[node->id()] =
147                   call_descriptor->GetReturnType(0).representation();
148             } else {
149               representation_vector_[node->id()] =
150                   MachineRepresentation::kTagged;
151             }
152             break;
153           }
154           case IrOpcode::kWord32AtomicStore:
155           case IrOpcode::kWord64AtomicStore:
156             representation_vector_[node->id()] =
157                 PromoteRepresentation(AtomicStoreRepresentationOf(node->op()));
158             break;
159           case IrOpcode::kWord32AtomicPairLoad:
160           case IrOpcode::kWord32AtomicPairStore:
161           case IrOpcode::kWord32AtomicPairAdd:
162           case IrOpcode::kWord32AtomicPairSub:
163           case IrOpcode::kWord32AtomicPairAnd:
164           case IrOpcode::kWord32AtomicPairOr:
165           case IrOpcode::kWord32AtomicPairXor:
166           case IrOpcode::kWord32AtomicPairExchange:
167           case IrOpcode::kWord32AtomicPairCompareExchange:
168             representation_vector_[node->id()] = MachineRepresentation::kWord32;
169             break;
170           case IrOpcode::kWord32AtomicExchange:
171           case IrOpcode::kWord32AtomicCompareExchange:
172           case IrOpcode::kWord32AtomicAdd:
173           case IrOpcode::kWord32AtomicSub:
174           case IrOpcode::kWord32AtomicAnd:
175           case IrOpcode::kWord32AtomicOr:
176           case IrOpcode::kWord32AtomicXor:
177           case IrOpcode::kWord64AtomicExchange:
178           case IrOpcode::kWord64AtomicCompareExchange:
179           case IrOpcode::kWord64AtomicAdd:
180           case IrOpcode::kWord64AtomicSub:
181           case IrOpcode::kWord64AtomicAnd:
182           case IrOpcode::kWord64AtomicOr:
183           case IrOpcode::kWord64AtomicXor:
184             representation_vector_[node->id()] = PromoteRepresentation(
185                 AtomicOpType(node->op()).representation());
186             break;
187           case IrOpcode::kStore:
188           case IrOpcode::kProtectedStore:
189             representation_vector_[node->id()] = PromoteRepresentation(
190                 StoreRepresentationOf(node->op()).representation());
191             break;
192           case IrOpcode::kUnalignedStore:
193             representation_vector_[node->id()] = PromoteRepresentation(
194                 UnalignedStoreRepresentationOf(node->op()));
195             break;
196           case IrOpcode::kHeapConstant:
197             representation_vector_[node->id()] =
198                 MachineRepresentation::kTaggedPointer;
199             break;
200           case IrOpcode::kNumberConstant:
201           case IrOpcode::kDelayedStringConstant:
202           case IrOpcode::kChangeBitToTagged:
203           case IrOpcode::kIfException:
204           case IrOpcode::kOsrValue:
205           case IrOpcode::kChangeInt32ToTagged:
206           case IrOpcode::kChangeUint32ToTagged:
207           case IrOpcode::kBitcastWordToTagged:
208           case IrOpcode::kTaggedPoisonOnSpeculation:
209             representation_vector_[node->id()] = MachineRepresentation::kTagged;
210             break;
211           case IrOpcode::kWord32PoisonOnSpeculation:
212             representation_vector_[node->id()] = MachineRepresentation::kWord32;
213             break;
214           case IrOpcode::kWord64PoisonOnSpeculation:
215             representation_vector_[node->id()] = MachineRepresentation::kWord64;
216             break;
217           case IrOpcode::kCompressedHeapConstant:
218             representation_vector_[node->id()] =
219                 MachineRepresentation::kCompressedPointer;
220             break;
221           case IrOpcode::kExternalConstant:
222             representation_vector_[node->id()] =
223                 MachineType::PointerRepresentation();
224             break;
225           case IrOpcode::kBitcastTaggedToWord:
226           case IrOpcode::kBitcastTaggedToWordForTagAndSmiBits:
227             representation_vector_[node->id()] =
228                 MachineType::PointerRepresentation();
229             break;
230           case IrOpcode::kBitcastWordToTaggedSigned:
231             representation_vector_[node->id()] =
232                 MachineRepresentation::kTaggedSigned;
233             break;
234           case IrOpcode::kWord32Equal:
235           case IrOpcode::kInt32LessThan:
236           case IrOpcode::kInt32LessThanOrEqual:
237           case IrOpcode::kUint32LessThan:
238           case IrOpcode::kUint32LessThanOrEqual:
239           case IrOpcode::kWord64Equal:
240           case IrOpcode::kInt64LessThan:
241           case IrOpcode::kInt64LessThanOrEqual:
242           case IrOpcode::kUint64LessThan:
243           case IrOpcode::kUint64LessThanOrEqual:
244           case IrOpcode::kFloat32Equal:
245           case IrOpcode::kFloat32LessThan:
246           case IrOpcode::kFloat32LessThanOrEqual:
247           case IrOpcode::kFloat64Equal:
248           case IrOpcode::kFloat64LessThan:
249           case IrOpcode::kFloat64LessThanOrEqual:
250           case IrOpcode::kChangeTaggedToBit:
251           case IrOpcode::kStackPointerGreaterThan:
252             representation_vector_[node->id()] = MachineRepresentation::kBit;
253             break;
254 #define LABEL(opcode) case IrOpcode::k##opcode:
255           case IrOpcode::kTruncateInt64ToInt32:
256           case IrOpcode::kTruncateFloat32ToInt32:
257           case IrOpcode::kTruncateFloat32ToUint32:
258           case IrOpcode::kBitcastFloat32ToInt32:
259           case IrOpcode::kI32x4ExtractLane:
260           case IrOpcode::kI16x8ExtractLaneU:
261           case IrOpcode::kI16x8ExtractLaneS:
262           case IrOpcode::kI8x16ExtractLaneU:
263           case IrOpcode::kI8x16ExtractLaneS:
264           case IrOpcode::kInt32Constant:
265           case IrOpcode::kRelocatableInt32Constant:
266           case IrOpcode::kTruncateFloat64ToWord32:
267           case IrOpcode::kTruncateFloat64ToUint32:
268           case IrOpcode::kChangeFloat64ToInt32:
269           case IrOpcode::kChangeFloat64ToUint32:
270           case IrOpcode::kRoundFloat64ToInt32:
271           case IrOpcode::kFloat64ExtractLowWord32:
272           case IrOpcode::kFloat64ExtractHighWord32:
273             MACHINE_UNOP_32_LIST(LABEL)
274             MACHINE_BINOP_32_LIST(LABEL) {
275               representation_vector_[node->id()] =
276                   MachineRepresentation::kWord32;
277             }
278             break;
279           case IrOpcode::kChangeInt32ToInt64:
280           case IrOpcode::kChangeUint32ToUint64:
281           case IrOpcode::kInt64Constant:
282           case IrOpcode::kRelocatableInt64Constant:
283           case IrOpcode::kBitcastFloat64ToInt64:
284           case IrOpcode::kChangeFloat64ToInt64:
285           case IrOpcode::kChangeFloat64ToUint64:
286             MACHINE_BINOP_64_LIST(LABEL) {
287               representation_vector_[node->id()] =
288                   MachineRepresentation::kWord64;
289             }
290             break;
291           case IrOpcode::kRoundInt32ToFloat32:
292           case IrOpcode::kRoundUint32ToFloat32:
293           case IrOpcode::kRoundInt64ToFloat32:
294           case IrOpcode::kRoundUint64ToFloat32:
295           case IrOpcode::kBitcastInt32ToFloat32:
296           case IrOpcode::kFloat32Constant:
297           case IrOpcode::kTruncateFloat64ToFloat32:
298             MACHINE_FLOAT32_BINOP_LIST(LABEL)
299             MACHINE_FLOAT32_UNOP_LIST(LABEL) {
300               representation_vector_[node->id()] =
301                   MachineRepresentation::kFloat32;
302             }
303             break;
304           case IrOpcode::kRoundInt64ToFloat64:
305           case IrOpcode::kRoundUint64ToFloat64:
306           case IrOpcode::kChangeFloat32ToFloat64:
307           case IrOpcode::kChangeInt32ToFloat64:
308           case IrOpcode::kChangeUint32ToFloat64:
309           case IrOpcode::kFloat64InsertLowWord32:
310           case IrOpcode::kFloat64InsertHighWord32:
311           case IrOpcode::kFloat64Constant:
312           case IrOpcode::kFloat64SilenceNaN:
313             MACHINE_FLOAT64_BINOP_LIST(LABEL)
314             MACHINE_FLOAT64_UNOP_LIST(LABEL) {
315               representation_vector_[node->id()] =
316                   MachineRepresentation::kFloat64;
317             }
318             break;
319           case IrOpcode::kI32x4ReplaceLane:
320           case IrOpcode::kI32x4Splat:
321             representation_vector_[node->id()] =
322                 MachineRepresentation::kSimd128;
323             break;
324 #undef LABEL
325           default:
326             break;
327         }
328       }
329     }
330   }
331 
332   Schedule const* const schedule_;
333   Linkage const* const linkage_;
334   ZoneVector<MachineRepresentation> representation_vector_;
335   BasicBlock* current_block_;
336 };
337 
338 class MachineRepresentationChecker {
339  public:
MachineRepresentationChecker(Schedule const * const schedule,MachineRepresentationInferrer const * const inferrer,bool is_stub,const char * name)340   MachineRepresentationChecker(
341       Schedule const* const schedule,
342       MachineRepresentationInferrer const* const inferrer, bool is_stub,
343       const char* name)
344       : schedule_(schedule),
345         inferrer_(inferrer),
346         is_stub_(is_stub),
347         name_(name),
348         current_block_(nullptr) {}
349 
Run()350   void Run() {
351     BasicBlockVector const* blocks = schedule_->all_blocks();
352     for (BasicBlock* block : *blocks) {
353       current_block_ = block;
354       for (size_t i = 0; i <= block->NodeCount(); ++i) {
355         Node const* node =
356             i < block->NodeCount() ? block->NodeAt(i) : block->control_input();
357         if (node == nullptr) {
358           DCHECK_EQ(block->NodeCount(), i);
359           break;
360         }
361         switch (node->opcode()) {
362           case IrOpcode::kCall:
363           case IrOpcode::kTailCall:
364             CheckCallInputs(node);
365             break;
366           case IrOpcode::kChangeBitToTagged:
367             CHECK_EQ(MachineRepresentation::kBit,
368                      inferrer_->GetRepresentation(node->InputAt(0)));
369             break;
370           case IrOpcode::kChangeTaggedToBit:
371             CHECK_EQ(MachineRepresentation::kTagged,
372                      inferrer_->GetRepresentation(node->InputAt(0)));
373             break;
374           case IrOpcode::kRoundInt64ToFloat64:
375           case IrOpcode::kRoundUint64ToFloat64:
376           case IrOpcode::kRoundInt64ToFloat32:
377           case IrOpcode::kRoundUint64ToFloat32:
378           case IrOpcode::kTruncateInt64ToInt32:
379             CheckValueInputForInt64Op(node, 0);
380             break;
381           case IrOpcode::kBitcastWordToTagged:
382           case IrOpcode::kBitcastWordToTaggedSigned:
383             CheckValueInputRepresentationIs(
384                 node, 0, MachineType::PointerRepresentation());
385             break;
386           case IrOpcode::kWord32PoisonOnSpeculation:
387             CheckValueInputRepresentationIs(node, 0,
388                                             MachineRepresentation::kWord32);
389             break;
390           case IrOpcode::kWord64PoisonOnSpeculation:
391             CheckValueInputRepresentationIs(node, 0,
392                                             MachineRepresentation::kWord64);
393             break;
394           case IrOpcode::kBitcastTaggedToWord:
395           case IrOpcode::kBitcastTaggedToWordForTagAndSmiBits:
396             if (COMPRESS_POINTERS_BOOL) {
397               CheckValueInputIsCompressedOrTagged(node, 0);
398             } else {
399               CheckValueInputIsTagged(node, 0);
400             }
401             break;
402           case IrOpcode::kTaggedPoisonOnSpeculation:
403             CheckValueInputIsTagged(node, 0);
404             break;
405           case IrOpcode::kTruncateFloat64ToWord32:
406           case IrOpcode::kTruncateFloat64ToUint32:
407           case IrOpcode::kTruncateFloat64ToFloat32:
408           case IrOpcode::kChangeFloat64ToInt32:
409           case IrOpcode::kChangeFloat64ToUint32:
410           case IrOpcode::kRoundFloat64ToInt32:
411           case IrOpcode::kFloat64ExtractLowWord32:
412           case IrOpcode::kFloat64ExtractHighWord32:
413           case IrOpcode::kBitcastFloat64ToInt64:
414           case IrOpcode::kTryTruncateFloat64ToInt64:
415             CheckValueInputForFloat64Op(node, 0);
416             break;
417           case IrOpcode::kWord64Equal:
418             if (Is64() && !COMPRESS_POINTERS_BOOL) {
419               CheckValueInputIsTaggedOrPointer(node, 0);
420               CheckValueInputIsTaggedOrPointer(node, 1);
421               if (!is_stub_) {
422                 CheckValueInputRepresentationIs(
423                     node, 1, inferrer_->GetRepresentation(node->InputAt(0)));
424               }
425             } else {
426               CheckValueInputForInt64Op(node, 0);
427               CheckValueInputForInt64Op(node, 1);
428             }
429             break;
430           case IrOpcode::kInt64LessThan:
431           case IrOpcode::kInt64LessThanOrEqual:
432           case IrOpcode::kUint64LessThan:
433           case IrOpcode::kUint64LessThanOrEqual:
434             CheckValueInputForInt64Op(node, 0);
435             CheckValueInputForInt64Op(node, 1);
436             break;
437           case IrOpcode::kI32x4ExtractLane:
438           case IrOpcode::kI16x8ExtractLaneU:
439           case IrOpcode::kI16x8ExtractLaneS:
440           case IrOpcode::kI8x16ExtractLaneU:
441           case IrOpcode::kI8x16ExtractLaneS:
442             CheckValueInputRepresentationIs(node, 0,
443                                             MachineRepresentation::kSimd128);
444             break;
445           case IrOpcode::kI32x4ReplaceLane:
446             CheckValueInputRepresentationIs(node, 0,
447                                             MachineRepresentation::kSimd128);
448             CheckValueInputForInt32Op(node, 1);
449             break;
450           case IrOpcode::kI32x4Splat:
451             CheckValueInputForInt32Op(node, 0);
452             break;
453 #define LABEL(opcode) case IrOpcode::k##opcode:
454           case IrOpcode::kChangeInt32ToTagged:
455           case IrOpcode::kChangeUint32ToTagged:
456           case IrOpcode::kChangeInt32ToFloat64:
457           case IrOpcode::kChangeUint32ToFloat64:
458           case IrOpcode::kRoundInt32ToFloat32:
459           case IrOpcode::kRoundUint32ToFloat32:
460           case IrOpcode::kBitcastInt32ToFloat32:
461           case IrOpcode::kBitcastWord32ToWord64:
462           case IrOpcode::kChangeInt32ToInt64:
463           case IrOpcode::kChangeUint32ToUint64:
464             MACHINE_UNOP_32_LIST(LABEL) { CheckValueInputForInt32Op(node, 0); }
465             break;
466           case IrOpcode::kWord32Equal:
467             if (Is32()) {
468               CheckValueInputIsTaggedOrPointer(node, 0);
469               CheckValueInputIsTaggedOrPointer(node, 1);
470               if (!is_stub_) {
471                 CheckValueInputRepresentationIs(
472                     node, 1, inferrer_->GetRepresentation(node->InputAt(0)));
473               }
474             } else {
475               if (COMPRESS_POINTERS_BOOL) {
476                 CheckValueInputIsCompressedOrTaggedOrInt32(node, 0);
477                 CheckValueInputIsCompressedOrTaggedOrInt32(node, 1);
478               } else {
479                 CheckValueIsTaggedOrInt32(node, 0);
480                 CheckValueIsTaggedOrInt32(node, 1);
481               }
482             }
483             break;
484 
485           case IrOpcode::kInt32LessThan:
486           case IrOpcode::kInt32LessThanOrEqual:
487           case IrOpcode::kUint32LessThan:
488           case IrOpcode::kUint32LessThanOrEqual:
489             MACHINE_BINOP_32_LIST(LABEL) {
490               CheckValueInputForInt32Op(node, 0);
491               CheckValueInputForInt32Op(node, 1);
492             }
493             break;
494             MACHINE_BINOP_64_LIST(LABEL) {
495               CheckValueInputForInt64Op(node, 0);
496               CheckValueInputForInt64Op(node, 1);
497             }
498             break;
499           case IrOpcode::kFloat32Equal:
500           case IrOpcode::kFloat32LessThan:
501           case IrOpcode::kFloat32LessThanOrEqual:
502             MACHINE_FLOAT32_BINOP_LIST(LABEL) {
503               CheckValueInputForFloat32Op(node, 0);
504               CheckValueInputForFloat32Op(node, 1);
505             }
506             break;
507           case IrOpcode::kChangeFloat32ToFloat64:
508           case IrOpcode::kTruncateFloat32ToInt32:
509           case IrOpcode::kTruncateFloat32ToUint32:
510           case IrOpcode::kBitcastFloat32ToInt32:
511             MACHINE_FLOAT32_UNOP_LIST(LABEL) {
512               CheckValueInputForFloat32Op(node, 0);
513             }
514             break;
515           case IrOpcode::kFloat64Equal:
516           case IrOpcode::kFloat64LessThan:
517           case IrOpcode::kFloat64LessThanOrEqual:
518             MACHINE_FLOAT64_BINOP_LIST(LABEL) {
519               CheckValueInputForFloat64Op(node, 0);
520               CheckValueInputForFloat64Op(node, 1);
521             }
522             break;
523           case IrOpcode::kFloat64SilenceNaN:
524           case IrOpcode::kChangeFloat64ToInt64:
525           case IrOpcode::kChangeFloat64ToUint64:
526             MACHINE_FLOAT64_UNOP_LIST(LABEL) {
527               CheckValueInputForFloat64Op(node, 0);
528             }
529             break;
530 #undef LABEL
531           case IrOpcode::kFloat64InsertLowWord32:
532           case IrOpcode::kFloat64InsertHighWord32:
533             CheckValueInputForFloat64Op(node, 0);
534             CheckValueInputForInt32Op(node, 1);
535             break;
536           case IrOpcode::kParameter:
537           case IrOpcode::kProjection:
538             break;
539           case IrOpcode::kAbortCSAAssert:
540             CheckValueInputIsTagged(node, 0);
541             break;
542           case IrOpcode::kLoad:
543           case IrOpcode::kWord32AtomicLoad:
544           case IrOpcode::kWord32AtomicPairLoad:
545           case IrOpcode::kWord64AtomicLoad:
546           case IrOpcode::kPoisonedLoad:
547             CheckValueInputIsTaggedOrPointer(node, 0);
548             CheckValueInputRepresentationIs(
549                 node, 1, MachineType::PointerRepresentation());
550             break;
551           case IrOpcode::kWord32AtomicPairAdd:
552           case IrOpcode::kWord32AtomicPairSub:
553           case IrOpcode::kWord32AtomicPairAnd:
554           case IrOpcode::kWord32AtomicPairOr:
555           case IrOpcode::kWord32AtomicPairXor:
556           case IrOpcode::kWord32AtomicPairStore:
557           case IrOpcode::kWord32AtomicPairExchange:
558             CheckValueInputRepresentationIs(node, 3,
559                                             MachineRepresentation::kWord32);
560             V8_FALLTHROUGH;
561           case IrOpcode::kStore:
562           case IrOpcode::kWord32AtomicStore:
563           case IrOpcode::kWord32AtomicExchange:
564           case IrOpcode::kWord32AtomicAdd:
565           case IrOpcode::kWord32AtomicSub:
566           case IrOpcode::kWord32AtomicAnd:
567           case IrOpcode::kWord32AtomicOr:
568           case IrOpcode::kWord32AtomicXor:
569           case IrOpcode::kWord64AtomicStore:
570           case IrOpcode::kWord64AtomicExchange:
571           case IrOpcode::kWord64AtomicAdd:
572           case IrOpcode::kWord64AtomicSub:
573           case IrOpcode::kWord64AtomicAnd:
574           case IrOpcode::kWord64AtomicOr:
575           case IrOpcode::kWord64AtomicXor:
576             CheckValueInputIsTaggedOrPointer(node, 0);
577             CheckValueInputRepresentationIs(
578                 node, 1, MachineType::PointerRepresentation());
579             switch (inferrer_->GetRepresentation(node)) {
580               case MachineRepresentation::kTagged:
581               case MachineRepresentation::kTaggedPointer:
582               case MachineRepresentation::kTaggedSigned:
583                 if (COMPRESS_POINTERS_BOOL &&
584                     node->opcode() == IrOpcode::kStore &&
585                     CanBeTaggedPointer(
586                         StoreRepresentationOf(node->op()).representation())) {
587                   CheckValueInputIsCompressedOrTagged(node, 2);
588                 } else {
589                   CheckValueInputIsTagged(node, 2);
590                 }
591                 break;
592               default:
593                 CheckValueInputRepresentationIs(
594                     node, 2, inferrer_->GetRepresentation(node));
595             }
596             break;
597           case IrOpcode::kWord32AtomicPairCompareExchange:
598             CheckValueInputRepresentationIs(node, 4,
599                                             MachineRepresentation::kWord32);
600             CheckValueInputRepresentationIs(node, 5,
601                                             MachineRepresentation::kWord32);
602             V8_FALLTHROUGH;
603           case IrOpcode::kWord32AtomicCompareExchange:
604           case IrOpcode::kWord64AtomicCompareExchange:
605             CheckValueInputIsTaggedOrPointer(node, 0);
606             CheckValueInputRepresentationIs(
607                 node, 1, MachineType::PointerRepresentation());
608             switch (inferrer_->GetRepresentation(node)) {
609               case MachineRepresentation::kTagged:
610               case MachineRepresentation::kTaggedPointer:
611               case MachineRepresentation::kTaggedSigned:
612                 CheckValueInputIsTagged(node, 2);
613                 CheckValueInputIsTagged(node, 3);
614                 break;
615               default:
616                 CheckValueInputRepresentationIs(
617                     node, 2, inferrer_->GetRepresentation(node));
618                 CheckValueInputRepresentationIs(
619                     node, 3, inferrer_->GetRepresentation(node));
620             }
621             break;
622           case IrOpcode::kPhi:
623             switch (inferrer_->GetRepresentation(node)) {
624               case MachineRepresentation::kTagged:
625               case MachineRepresentation::kTaggedPointer:
626                 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
627                   CheckValueInputIsTagged(node, i);
628                 }
629                 break;
630               case MachineRepresentation::kTaggedSigned:
631                 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
632                   if (COMPRESS_POINTERS_BOOL) {
633                     CheckValueInputIsCompressedOrTagged(node, i);
634                   } else {
635                     CheckValueInputIsTagged(node, i);
636                   }
637                 }
638                 break;
639               case MachineRepresentation::kCompressed:
640               case MachineRepresentation::kCompressedPointer:
641                 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
642                     CheckValueInputIsCompressedOrTagged(node, i);
643                 }
644                 break;
645               case MachineRepresentation::kWord32:
646                 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
647                   CheckValueInputForInt32Op(node, i);
648                 }
649                 break;
650               default:
651                 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
652                   CheckValueInputRepresentationIs(
653                       node, i, inferrer_->GetRepresentation(node));
654                 }
655                 break;
656             }
657             break;
658           case IrOpcode::kBranch:
659           case IrOpcode::kSwitch:
660             CheckValueInputForInt32Op(node, 0);
661             break;
662           case IrOpcode::kReturn: {
663             // TODO(ishell): enable once the pop count parameter type becomes
664             // MachineType::PointerRepresentation(). Currently it's int32 or
665             // word-size.
666             // CheckValueInputRepresentationIs(
667             //     node, 0, MachineType::PointerRepresentation());  // Pop count
668             size_t return_count = inferrer_->call_descriptor()->ReturnCount();
669             for (size_t i = 0; i < return_count; i++) {
670               MachineType type = inferrer_->call_descriptor()->GetReturnType(i);
671               int input_index = static_cast<int>(i + 1);
672               switch (type.representation()) {
673                 case MachineRepresentation::kTagged:
674                 case MachineRepresentation::kTaggedPointer:
675                 case MachineRepresentation::kTaggedSigned:
676                   CheckValueInputIsTagged(node, input_index);
677                   break;
678                 case MachineRepresentation::kWord32:
679                   CheckValueInputForInt32Op(node, input_index);
680                   break;
681                 default:
682                   CheckValueInputRepresentationIs(node, input_index,
683                                                   type.representation());
684                   break;
685               }
686             }
687             break;
688           }
689           case IrOpcode::kStackPointerGreaterThan:
690             CheckValueInputRepresentationIs(
691                 node, 0, MachineType::PointerRepresentation());
692             break;
693           case IrOpcode::kThrow:
694           case IrOpcode::kTypedStateValues:
695           case IrOpcode::kFrameState:
696           case IrOpcode::kStaticAssert:
697             break;
698           default:
699             if (node->op()->ValueInputCount() != 0) {
700               std::stringstream str;
701               str << "Node #" << node->id() << ":" << *node->op()
702                   << " in the machine graph is not being checked.";
703               PrintDebugHelp(str, node);
704               FATAL("%s", str.str().c_str());
705             }
706             break;
707         }
708       }
709     }
710   }
711 
712  private:
Is32()713   static bool Is32() {
714     return MachineType::PointerRepresentation() ==
715            MachineRepresentation::kWord32;
716   }
Is64()717   static bool Is64() {
718     return MachineType::PointerRepresentation() ==
719            MachineRepresentation::kWord64;
720   }
721 
CheckValueInputRepresentationIs(Node const * node,int index,MachineRepresentation representation)722   void CheckValueInputRepresentationIs(Node const* node, int index,
723                                        MachineRepresentation representation) {
724     Node const* input = node->InputAt(index);
725     MachineRepresentation input_representation =
726         inferrer_->GetRepresentation(input);
727     if (input_representation != representation) {
728       std::stringstream str;
729       str << "TypeError: node #" << node->id() << ":" << *node->op()
730           << " uses node #" << input->id() << ":" << *input->op() << ":"
731           << input_representation << " which doesn't have a " << representation
732           << " representation.";
733       PrintDebugHelp(str, node);
734       FATAL("%s", str.str().c_str());
735     }
736   }
737 
CheckValueInputIsCompressed(Node const * node,int index)738   void CheckValueInputIsCompressed(Node const* node, int index) {
739     Node const* input = node->InputAt(index);
740     switch (inferrer_->GetRepresentation(input)) {
741       case MachineRepresentation::kCompressed:
742       case MachineRepresentation::kCompressedPointer:
743         return;
744       default:
745         break;
746     }
747     std::ostringstream str;
748     str << "TypeError: node #" << node->id() << ":" << *node->op()
749         << " uses node #" << input->id() << ":" << *input->op()
750         << " which doesn't have a compressed representation.";
751     PrintDebugHelp(str, node);
752     FATAL("%s", str.str().c_str());
753   }
754 
CheckValueInputIsTagged(Node const * node,int index)755   void CheckValueInputIsTagged(Node const* node, int index) {
756     Node const* input = node->InputAt(index);
757     switch (inferrer_->GetRepresentation(input)) {
758       case MachineRepresentation::kTagged:
759       case MachineRepresentation::kTaggedPointer:
760       case MachineRepresentation::kTaggedSigned:
761         return;
762       default:
763         break;
764     }
765     std::ostringstream str;
766     str << "TypeError: node #" << node->id() << ":" << *node->op()
767         << " uses node #" << input->id() << ":" << *input->op()
768         << " which doesn't have a tagged representation.";
769     PrintDebugHelp(str, node);
770     FATAL("%s", str.str().c_str());
771   }
772 
CheckValueInputIsCompressedOrTagged(Node const * node,int index)773   void CheckValueInputIsCompressedOrTagged(Node const* node, int index) {
774     Node const* input = node->InputAt(index);
775     switch (inferrer_->GetRepresentation(input)) {
776       case MachineRepresentation::kCompressed:
777       case MachineRepresentation::kCompressedPointer:
778       case MachineRepresentation::kTagged:
779       case MachineRepresentation::kTaggedPointer:
780       case MachineRepresentation::kTaggedSigned:
781         return;
782       default:
783         break;
784     }
785     std::ostringstream str;
786     str << "TypeError: node #" << node->id() << ":" << *node->op()
787         << " uses node #" << input->id() << ":" << *input->op()
788         << " which doesn't have a compressed or tagged representation.";
789     PrintDebugHelp(str, node);
790     FATAL("%s", str.str().c_str());
791   }
792 
CheckValueInputIsCompressedOrTaggedOrInt32(Node const * node,int index)793   void CheckValueInputIsCompressedOrTaggedOrInt32(Node const* node, int index) {
794     Node const* input = node->InputAt(index);
795     switch (inferrer_->GetRepresentation(input)) {
796       case MachineRepresentation::kCompressed:
797       case MachineRepresentation::kCompressedPointer:
798         return;
799       case MachineRepresentation::kTagged:
800       case MachineRepresentation::kTaggedPointer:
801       case MachineRepresentation::kTaggedSigned:
802         return;
803       case MachineRepresentation::kBit:
804       case MachineRepresentation::kWord8:
805       case MachineRepresentation::kWord16:
806       case MachineRepresentation::kWord32:
807         return;
808       default:
809         break;
810     }
811     std::ostringstream str;
812     str << "TypeError: node #" << node->id() << ":" << *node->op()
813         << " uses node #" << input->id() << ":" << *input->op()
814         << " which doesn't have a compressed, tagged, or int32 representation.";
815     PrintDebugHelp(str, node);
816     FATAL("%s", str.str().c_str());
817   }
818 
CheckValueInputIsTaggedOrPointer(Node const * node,int index)819   void CheckValueInputIsTaggedOrPointer(Node const* node, int index) {
820     Node const* input = node->InputAt(index);
821     switch (inferrer_->GetRepresentation(input)) {
822       case MachineRepresentation::kTagged:
823       case MachineRepresentation::kTaggedPointer:
824       case MachineRepresentation::kTaggedSigned:
825         return;
826       case MachineRepresentation::kBit:
827       case MachineRepresentation::kWord8:
828       case MachineRepresentation::kWord16:
829       case MachineRepresentation::kWord32:
830         if (Is32()) {
831           return;
832         }
833         break;
834       case MachineRepresentation::kWord64:
835         if (Is64()) {
836           return;
837         }
838         break;
839       default:
840         break;
841     }
842     if (inferrer_->GetRepresentation(input) !=
843         MachineType::PointerRepresentation()) {
844       std::ostringstream str;
845       str << "TypeError: node #" << node->id() << ":" << *node->op()
846           << " uses node #" << input->id() << ":" << *input->op()
847           << " which doesn't have a tagged or pointer representation.";
848       PrintDebugHelp(str, node);
849       FATAL("%s", str.str().c_str());
850     }
851   }
852 
CheckValueInputForInt32Op(Node const * node,int index)853   void CheckValueInputForInt32Op(Node const* node, int index) {
854     Node const* input = node->InputAt(index);
855     switch (inferrer_->GetRepresentation(input)) {
856       case MachineRepresentation::kBit:
857       case MachineRepresentation::kWord8:
858       case MachineRepresentation::kWord16:
859       case MachineRepresentation::kWord32:
860         return;
861       case MachineRepresentation::kNone: {
862         std::ostringstream str;
863         str << "TypeError: node #" << input->id() << ":" << *input->op()
864             << " is untyped.";
865         PrintDebugHelp(str, node);
866         FATAL("%s", str.str().c_str());
867         break;
868       }
869       default:
870         break;
871     }
872     std::ostringstream str;
873     str << "TypeError: node #" << node->id() << ":" << *node->op()
874         << " uses node #" << input->id() << ":" << *input->op()
875         << " which doesn't have an int32-compatible representation.";
876     PrintDebugHelp(str, node);
877     FATAL("%s", str.str().c_str());
878   }
879 
CheckValueIsTaggedOrInt32(Node const * node,int index)880   void CheckValueIsTaggedOrInt32(Node const* node, int index) {
881     Node const* input = node->InputAt(index);
882     switch (inferrer_->GetRepresentation(input)) {
883       case MachineRepresentation::kBit:
884       case MachineRepresentation::kWord8:
885       case MachineRepresentation::kWord16:
886       case MachineRepresentation::kWord32:
887         return;
888       case MachineRepresentation::kTagged:
889       case MachineRepresentation::kTaggedPointer:
890         return;
891       default:
892         break;
893     }
894     std::ostringstream str;
895     str << "TypeError: node #" << node->id() << ":" << *node->op()
896         << " uses node #" << input->id() << ":" << *input->op()
897         << " which doesn't have a tagged or int32-compatible "
898            "representation.";
899     PrintDebugHelp(str, node);
900     FATAL("%s", str.str().c_str());
901   }
902 
CheckValueInputForInt64Op(Node const * node,int index)903   void CheckValueInputForInt64Op(Node const* node, int index) {
904     Node const* input = node->InputAt(index);
905     MachineRepresentation input_representation =
906         inferrer_->GetRepresentation(input);
907     switch (input_representation) {
908       case MachineRepresentation::kWord64:
909         return;
910       case MachineRepresentation::kNone: {
911         std::ostringstream str;
912         str << "TypeError: node #" << input->id() << ":" << *input->op()
913             << " is untyped.";
914         PrintDebugHelp(str, node);
915         FATAL("%s", str.str().c_str());
916         break;
917       }
918 
919       default:
920         break;
921     }
922     std::ostringstream str;
923     str << "TypeError: node #" << node->id() << ":" << *node->op()
924         << " uses node #" << input->id() << ":" << *input->op() << ":"
925         << input_representation
926         << " which doesn't have a kWord64 representation.";
927     PrintDebugHelp(str, node);
928     FATAL("%s", str.str().c_str());
929   }
930 
CheckValueInputForFloat32Op(Node const * node,int index)931   void CheckValueInputForFloat32Op(Node const* node, int index) {
932     Node const* input = node->InputAt(index);
933     if (MachineRepresentation::kFloat32 ==
934         inferrer_->GetRepresentation(input)) {
935       return;
936     }
937     std::ostringstream str;
938     str << "TypeError: node #" << node->id() << ":" << *node->op()
939         << " uses node #" << input->id() << ":" << *input->op()
940         << " which doesn't have a kFloat32 representation.";
941     PrintDebugHelp(str, node);
942     FATAL("%s", str.str().c_str());
943   }
944 
CheckValueInputForFloat64Op(Node const * node,int index)945   void CheckValueInputForFloat64Op(Node const* node, int index) {
946     Node const* input = node->InputAt(index);
947     if (MachineRepresentation::kFloat64 ==
948         inferrer_->GetRepresentation(input)) {
949       return;
950     }
951     std::ostringstream str;
952     str << "TypeError: node #" << node->id() << ":" << *node->op()
953         << " uses node #" << input->id() << ":" << *input->op()
954         << " which doesn't have a kFloat64 representation.";
955     PrintDebugHelp(str, node);
956     FATAL("%s", str.str().c_str());
957   }
958 
CheckCallInputs(Node const * node)959   void CheckCallInputs(Node const* node) {
960     auto call_descriptor = CallDescriptorOf(node->op());
961     std::ostringstream str;
962     bool should_log_error = false;
963     for (size_t i = 0; i < call_descriptor->InputCount(); ++i) {
964       Node const* input = node->InputAt(static_cast<int>(i));
965       MachineRepresentation const input_type =
966           inferrer_->GetRepresentation(input);
967       MachineRepresentation const expected_input_type =
968           call_descriptor->GetInputType(i).representation();
969       if (!IsCompatible(expected_input_type, input_type)) {
970         if (!should_log_error) {
971           should_log_error = true;
972           str << "TypeError: node #" << node->id() << ":" << *node->op()
973               << " has wrong type for:" << std::endl;
974         } else {
975           str << std::endl;
976         }
977         str << " * input " << i << " (" << input->id() << ":" << *input->op()
978             << ") has a " << input_type
979             << " representation (expected: " << expected_input_type << ").";
980       }
981     }
982     if (should_log_error) {
983       PrintDebugHelp(str, node);
984       FATAL("%s", str.str().c_str());
985     }
986   }
987 
Intersect(MachineRepresentation lhs,MachineRepresentation rhs)988   bool Intersect(MachineRepresentation lhs, MachineRepresentation rhs) {
989     return (GetRepresentationProperties(lhs) &
990             GetRepresentationProperties(rhs)) != 0;
991   }
992 
993   enum RepresentationProperties { kIsPointer = 1, kIsTagged = 2 };
994 
GetRepresentationProperties(MachineRepresentation representation)995   int GetRepresentationProperties(MachineRepresentation representation) {
996     switch (representation) {
997       case MachineRepresentation::kTagged:
998       case MachineRepresentation::kTaggedPointer:
999         return kIsPointer | kIsTagged;
1000       case MachineRepresentation::kTaggedSigned:
1001         return kIsTagged;
1002       case MachineRepresentation::kWord32:
1003         return MachineRepresentation::kWord32 ==
1004                        MachineType::PointerRepresentation()
1005                    ? kIsPointer
1006                    : 0;
1007       case MachineRepresentation::kWord64:
1008         return MachineRepresentation::kWord64 ==
1009                        MachineType::PointerRepresentation()
1010                    ? kIsPointer
1011                    : 0;
1012       default:
1013         return 0;
1014     }
1015   }
1016 
IsCompatible(MachineRepresentation expected,MachineRepresentation actual)1017   bool IsCompatible(MachineRepresentation expected,
1018                     MachineRepresentation actual) {
1019     switch (expected) {
1020       case MachineRepresentation::kTagged:
1021         return IsAnyTagged(actual);
1022       case MachineRepresentation::kCompressed:
1023         return IsAnyCompressed(actual);
1024       case MachineRepresentation::kTaggedSigned:
1025       case MachineRepresentation::kTaggedPointer:
1026         // TODO(tebbi): At the moment, the machine graph doesn't contain
1027         // reliable information if a node is kTaggedSigned, kTaggedPointer or
1028         // kTagged, and often this is context-dependent. We should at least
1029         // check for obvious violations: kTaggedSigned where we expect
1030         // kTaggedPointer and the other way around, but at the moment, this
1031         // happens in dead code.
1032         return IsAnyTagged(actual);
1033       case MachineRepresentation::kCompressedPointer:
1034       case MachineRepresentation::kFloat32:
1035       case MachineRepresentation::kFloat64:
1036       case MachineRepresentation::kSimd128:
1037       case MachineRepresentation::kBit:
1038       case MachineRepresentation::kWord8:
1039       case MachineRepresentation::kWord16:
1040       case MachineRepresentation::kWord64:
1041         return expected == actual;
1042         break;
1043       case MachineRepresentation::kWord32:
1044         return (actual == MachineRepresentation::kBit ||
1045                 actual == MachineRepresentation::kWord8 ||
1046                 actual == MachineRepresentation::kWord16 ||
1047                 actual == MachineRepresentation::kWord32);
1048       case MachineRepresentation::kNone:
1049         UNREACHABLE();
1050     }
1051     return false;
1052   }
1053 
PrintDebugHelp(std::ostream & out,Node const * node)1054   void PrintDebugHelp(std::ostream& out, Node const* node) {
1055     if (DEBUG_BOOL) {
1056       out << "\n#     Current block: " << *current_block_;
1057       out << "\n#\n#     Specify option --csa-trap-on-node=" << name_ << ","
1058           << node->id() << " for debugging.";
1059     }
1060   }
1061 
1062   Schedule const* const schedule_;
1063   MachineRepresentationInferrer const* const inferrer_;
1064   bool is_stub_;
1065   const char* name_;
1066   BasicBlock* current_block_;
1067 };
1068 
1069 }  // namespace
1070 
Run(Graph * graph,Schedule const * const schedule,Linkage * linkage,bool is_stub,const char * name,Zone * temp_zone)1071 void MachineGraphVerifier::Run(Graph* graph, Schedule const* const schedule,
1072                                Linkage* linkage, bool is_stub, const char* name,
1073                                Zone* temp_zone) {
1074   MachineRepresentationInferrer representation_inferrer(schedule, graph,
1075                                                         linkage, temp_zone);
1076   MachineRepresentationChecker checker(schedule, &representation_inferrer,
1077                                        is_stub, name);
1078   checker.Run();
1079 }
1080 
1081 }  // namespace compiler
1082 }  // namespace internal
1083 }  // namespace v8
1084