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