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