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