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