OLD | NEW |
---|---|
(Empty) | |
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 MachineRepresentationInferrer(Schedule const* schedule, Graph const* graph, | |
25 Linkage* linkage, Zone* zone) | |
26 : schedule_(schedule), | |
27 linkage_(linkage), | |
28 representation_vector_(graph->NodeCount(), zone) { | |
Jarin
2016/10/05 08:16:17
Explicit initialization with MachineRepresentation
| |
29 Run(); | |
30 } | |
31 | |
32 MachineRepresentation GetRepresentation(Node const* node) const { | |
33 return representation_vector_.at(node->id()); | |
34 } | |
35 | |
36 private: | |
37 MachineRepresentation GetProjectionType(Node const* projection) { | |
38 size_t index = ProjectionIndexOf(projection->op()); | |
39 Node* input = projection->InputAt(0); | |
40 switch (input->opcode()) { | |
41 case IrOpcode::kInt32AddWithOverflow: | |
42 case IrOpcode::kInt32SubWithOverflow: | |
43 case IrOpcode::kInt32MulWithOverflow: | |
44 CHECK_LE(index, static_cast<size_t>(1)); | |
45 return index == 0 ? MachineRepresentation::kWord32 | |
46 : MachineRepresentation::kBit; | |
47 case IrOpcode::kInt64AddWithOverflow: | |
48 case IrOpcode::kInt64SubWithOverflow: | |
49 CHECK_LE(index, static_cast<size_t>(1)); | |
50 return index == 0 ? MachineRepresentation::kWord64 | |
51 : MachineRepresentation::kBit; | |
52 case IrOpcode::kTryTruncateFloat32ToInt64: | |
53 case IrOpcode::kTryTruncateFloat64ToInt64: | |
54 case IrOpcode::kTryTruncateFloat32ToUint64: | |
55 case IrOpcode::kTryTruncateFloat64ToUint64: | |
56 CHECK_LE(index, static_cast<size_t>(1)); | |
57 return index == 0 ? MachineRepresentation::kWord64 | |
58 : MachineRepresentation::kBit; | |
59 case IrOpcode::kCall: { | |
60 CallDescriptor const* desc = CallDescriptorOf(input->op()); | |
61 return desc->GetReturnType(index).representation(); | |
62 } | |
63 default: | |
64 return MachineRepresentation::kNone; | |
65 } | |
66 } | |
67 | |
68 void Run() { | |
69 auto blocks = schedule_->all_blocks(); | |
70 for (BasicBlock* block : *blocks) { | |
71 for (size_t i = 0; i <= block->NodeCount(); ++i) { | |
72 Node const* node = | |
73 i < block->NodeCount() ? block->NodeAt(i) : block->control_input(); | |
74 if (node == nullptr) { | |
75 DCHECK_EQ(block->NodeCount(), i); | |
76 break; | |
77 } | |
78 switch (node->opcode()) { | |
79 case IrOpcode::kParameter: | |
80 representation_vector_[node->id()] = | |
81 linkage_->GetParameterType(ParameterIndexOf(node->op())) | |
82 .representation(); | |
83 break; | |
84 case IrOpcode::kProjection: { | |
85 representation_vector_[node->id()] = GetProjectionType(node); | |
86 } break; | |
87 case IrOpcode::kTypedStateValues: | |
88 representation_vector_[node->id()] = MachineRepresentation::kNone; | |
89 break; | |
90 case IrOpcode::kAtomicLoad: | |
91 case IrOpcode::kLoad: | |
92 case IrOpcode::kProtectedLoad: | |
93 representation_vector_[node->id()] = | |
94 LoadRepresentationOf(node->op()).representation(); | |
95 break; | |
96 case IrOpcode::kCheckedLoad: | |
97 representation_vector_[node->id()] = | |
98 CheckedLoadRepresentationOf(node->op()).representation(); | |
99 break; | |
100 case IrOpcode::kLoadStackPointer: | |
101 case IrOpcode::kLoadFramePointer: | |
102 case IrOpcode::kLoadParentFramePointer: | |
103 representation_vector_[node->id()] = | |
104 MachineType::PointerRepresentation(); | |
105 break; | |
106 case IrOpcode::kPhi: | |
107 representation_vector_[node->id()] = | |
108 PhiRepresentationOf(node->op()); | |
109 break; | |
110 case IrOpcode::kCall: { | |
111 CallDescriptor const* desc = CallDescriptorOf(node->op()); | |
112 if (desc->ReturnCount() > 0) { | |
113 representation_vector_[node->id()] = | |
114 desc->GetReturnType(0).representation(); | |
115 } else { | |
116 representation_vector_[node->id()] = | |
117 MachineRepresentation::kTagged; | |
118 } | |
119 break; | |
120 } | |
121 case IrOpcode::kUnalignedLoad: | |
122 representation_vector_[node->id()] = | |
123 UnalignedLoadRepresentationOf(node->op()).representation(); | |
124 break; | |
125 case IrOpcode::kHeapConstant: | |
126 case IrOpcode::kNumberConstant: | |
127 case IrOpcode::kChangeBitToTagged: | |
128 case IrOpcode::kIfException: | |
129 case IrOpcode::kOsrValue: | |
130 case IrOpcode::kChangeInt32ToTagged: | |
131 case IrOpcode::kChangeUint32ToTagged: | |
132 case IrOpcode::kBitcastWordToTagged: | |
133 representation_vector_[node->id()] = MachineRepresentation::kTagged; | |
134 break; | |
135 case IrOpcode::kExternalConstant: | |
136 representation_vector_[node->id()] = | |
137 MachineType::PointerRepresentation(); | |
138 break; | |
139 case IrOpcode::kBitcastTaggedToWord: | |
140 representation_vector_[node->id()] = | |
141 MachineType::PointerRepresentation(); | |
142 break; | |
143 case IrOpcode::kBitcastWordToTaggedSigned: | |
144 representation_vector_[node->id()] = | |
145 MachineRepresentation::kTaggedSigned; | |
146 break; | |
147 case IrOpcode::kWord32Equal: | |
148 case IrOpcode::kInt32LessThan: | |
149 case IrOpcode::kInt32LessThanOrEqual: | |
150 case IrOpcode::kUint32LessThan: | |
151 case IrOpcode::kUint32LessThanOrEqual: | |
152 case IrOpcode::kWord64Equal: | |
153 case IrOpcode::kInt64LessThan: | |
154 case IrOpcode::kInt64LessThanOrEqual: | |
155 case IrOpcode::kUint64LessThan: | |
156 case IrOpcode::kUint64LessThanOrEqual: | |
157 case IrOpcode::kFloat32Equal: | |
158 case IrOpcode::kFloat32LessThan: | |
159 case IrOpcode::kFloat32LessThanOrEqual: | |
160 case IrOpcode::kFloat64Equal: | |
161 case IrOpcode::kFloat64LessThan: | |
162 case IrOpcode::kFloat64LessThanOrEqual: | |
163 case IrOpcode::kChangeTaggedToBit: | |
164 representation_vector_[node->id()] = MachineRepresentation::kBit; | |
165 break; | |
166 #define LABEL(opcode) case IrOpcode::k##opcode: | |
167 case IrOpcode::kTruncateInt64ToInt32: | |
168 case IrOpcode::kTruncateFloat32ToInt32: | |
169 case IrOpcode::kTruncateFloat32ToUint32: | |
170 case IrOpcode::kBitcastFloat32ToInt32: | |
171 case IrOpcode::kInt32x4ExtractLane: | |
172 case IrOpcode::kInt32Constant: | |
173 case IrOpcode::kRelocatableInt32Constant: | |
174 case IrOpcode::kTruncateFloat64ToWord32: | |
175 case IrOpcode::kTruncateFloat64ToUint32: | |
176 case IrOpcode::kChangeFloat64ToInt32: | |
177 case IrOpcode::kChangeFloat64ToUint32: | |
178 case IrOpcode::kRoundFloat64ToInt32: | |
179 case IrOpcode::kFloat64ExtractLowWord32: | |
180 case IrOpcode::kFloat64ExtractHighWord32: | |
181 MACHINE_UNOP_32_LIST(LABEL) | |
182 MACHINE_BINOP_32_LIST(LABEL) { | |
183 representation_vector_[node->id()] = | |
184 MachineRepresentation::kWord32; | |
185 } | |
186 break; | |
187 case IrOpcode::kChangeInt32ToInt64: | |
188 case IrOpcode::kChangeUint32ToUint64: | |
189 case IrOpcode::kInt64Constant: | |
190 case IrOpcode::kRelocatableInt64Constant: | |
191 case IrOpcode::kBitcastFloat64ToInt64: | |
192 MACHINE_BINOP_64_LIST(LABEL) { | |
193 representation_vector_[node->id()] = | |
194 MachineRepresentation::kWord64; | |
195 } | |
196 break; | |
197 case IrOpcode::kRoundInt32ToFloat32: | |
198 case IrOpcode::kRoundUint32ToFloat32: | |
199 case IrOpcode::kRoundInt64ToFloat32: | |
200 case IrOpcode::kRoundUint64ToFloat32: | |
201 case IrOpcode::kFloat32Constant: | |
202 case IrOpcode::kTruncateFloat64ToFloat32: | |
203 MACHINE_FLOAT32_BINOP_LIST(LABEL) | |
204 MACHINE_FLOAT32_UNOP_LIST(LABEL) { | |
205 representation_vector_[node->id()] = | |
206 MachineRepresentation::kFloat32; | |
207 } | |
208 break; | |
209 case IrOpcode::kRoundInt64ToFloat64: | |
210 case IrOpcode::kRoundUint64ToFloat64: | |
211 case IrOpcode::kChangeFloat32ToFloat64: | |
212 case IrOpcode::kChangeInt32ToFloat64: | |
213 case IrOpcode::kChangeUint32ToFloat64: | |
214 case IrOpcode::kFloat64Constant: | |
215 case IrOpcode::kFloat64SilenceNaN: | |
216 MACHINE_FLOAT64_BINOP_LIST(LABEL) | |
217 MACHINE_FLOAT64_UNOP_LIST(LABEL) { | |
218 representation_vector_[node->id()] = | |
219 MachineRepresentation::kFloat64; | |
220 } | |
221 break; | |
222 #undef LABEL | |
223 default: | |
224 break; | |
Jarin
2016/10/05 08:16:17
As discussed offline, it could be nicer to have a
| |
225 } | |
226 } | |
227 } | |
228 } | |
229 | |
230 Schedule const* const schedule_; | |
231 Linkage const* const linkage_; | |
232 ZoneVector<MachineRepresentation> representation_vector_; | |
233 }; | |
234 | |
235 class MachineRepresentationChecker { | |
236 public: | |
237 MachineRepresentationChecker(Schedule const* const schedule, | |
238 MachineRepresentationInferrer const* const typer) | |
239 : schedule_(schedule), typer_(typer) {} | |
240 | |
241 void Run() { | |
242 BasicBlockVector const* blocks = schedule_->all_blocks(); | |
243 for (BasicBlock* block : *blocks) { | |
244 for (size_t i = 0; i <= block->NodeCount(); ++i) { | |
245 Node const* node = | |
246 i < block->NodeCount() ? block->NodeAt(i) : block->control_input(); | |
247 if (node == nullptr) { | |
248 DCHECK_EQ(block->NodeCount(), i); | |
249 break; | |
250 } | |
251 switch (node->opcode()) { | |
252 case IrOpcode::kCall: | |
253 case IrOpcode::kTailCall: | |
254 CheckCallInputs(node); | |
255 break; | |
256 case IrOpcode::kChangeBitToTagged: | |
257 CHECK_EQ(MachineRepresentation::kBit, | |
258 typer_->GetRepresentation(node->InputAt(0))); | |
259 break; | |
260 case IrOpcode::kChangeTaggedToBit: | |
261 CHECK_EQ(MachineRepresentation::kTagged, | |
262 typer_->GetRepresentation(node->InputAt(0))); | |
263 break; | |
264 case IrOpcode::kRoundInt64ToFloat64: | |
265 case IrOpcode::kRoundUint64ToFloat64: | |
266 case IrOpcode::kRoundInt64ToFloat32: | |
267 case IrOpcode::kRoundUint64ToFloat32: | |
268 case IrOpcode::kTruncateInt64ToInt32: | |
269 CheckValueInputForInt64Op(node, 0); | |
270 break; | |
271 case IrOpcode::kBitcastWordToTagged: | |
272 case IrOpcode::kBitcastWordToTaggedSigned: | |
273 CheckValueInputRepresentationIs( | |
274 node, 0, MachineType::PointerRepresentation()); | |
275 break; | |
276 case IrOpcode::kBitcastTaggedToWord: | |
277 CheckValueInputIsTagged(node, 0); | |
278 break; | |
279 case IrOpcode::kTruncateFloat64ToWord32: | |
280 case IrOpcode::kTruncateFloat64ToUint32: | |
281 case IrOpcode::kTruncateFloat64ToFloat32: | |
282 case IrOpcode::kChangeFloat64ToInt32: | |
283 case IrOpcode::kChangeFloat64ToUint32: | |
284 case IrOpcode::kRoundFloat64ToInt32: | |
285 case IrOpcode::kFloat64ExtractLowWord32: | |
286 case IrOpcode::kFloat64ExtractHighWord32: | |
287 case IrOpcode::kBitcastFloat64ToInt64: | |
288 CheckValueInputForFloat64Op(node, 0); | |
289 break; | |
290 case IrOpcode::kWord64Equal: | |
291 CheckValueInputIsTaggedOrPointer(node, 0); | |
292 CheckValueInputRepresentationIs( | |
293 node, 1, typer_->GetRepresentation(node->InputAt(0))); | |
294 break; | |
295 case IrOpcode::kInt64LessThan: | |
296 case IrOpcode::kInt64LessThanOrEqual: | |
297 case IrOpcode::kUint64LessThan: | |
298 case IrOpcode::kUint64LessThanOrEqual: | |
299 CheckValueInputForInt64Op(node, 0); | |
300 CheckValueInputForInt64Op(node, 1); | |
301 break; | |
302 case IrOpcode::kInt32x4ExtractLane: | |
303 CheckValueInputRepresentationIs(node, 0, | |
304 MachineRepresentation::kSimd128); | |
305 break; | |
306 #define LABEL(opcode) case IrOpcode::k##opcode: | |
307 case IrOpcode::kChangeInt32ToTagged: | |
308 case IrOpcode::kChangeUint32ToTagged: | |
309 case IrOpcode::kChangeInt32ToFloat64: | |
310 case IrOpcode::kChangeUint32ToFloat64: | |
311 case IrOpcode::kRoundInt32ToFloat32: | |
312 case IrOpcode::kRoundUint32ToFloat32: | |
313 case IrOpcode::kChangeInt32ToInt64: | |
314 case IrOpcode::kChangeUint32ToUint64: | |
315 MACHINE_UNOP_32_LIST(LABEL) { CheckValueInputForInt32Op(node, 0); } | |
316 break; | |
317 case IrOpcode::kWord32Equal: | |
318 case IrOpcode::kInt32LessThan: | |
319 case IrOpcode::kInt32LessThanOrEqual: | |
320 case IrOpcode::kUint32LessThan: | |
321 case IrOpcode::kUint32LessThanOrEqual: | |
322 MACHINE_BINOP_32_LIST(LABEL) { | |
323 CheckValueInputForInt32Op(node, 0); | |
324 CheckValueInputForInt32Op(node, 1); | |
325 } | |
326 break; | |
327 MACHINE_BINOP_64_LIST(LABEL) { | |
328 CheckValueInputForInt64Op(node, 0); | |
329 CheckValueInputForInt64Op(node, 1); | |
330 } | |
331 break; | |
332 case IrOpcode::kFloat32Equal: | |
333 case IrOpcode::kFloat32LessThan: | |
334 case IrOpcode::kFloat32LessThanOrEqual: | |
335 MACHINE_FLOAT32_BINOP_LIST(LABEL) { | |
336 CheckValueInputForFloat32Op(node, 0); | |
337 CheckValueInputForFloat32Op(node, 1); | |
338 } | |
339 break; | |
340 case IrOpcode::kChangeFloat32ToFloat64: | |
341 case IrOpcode::kTruncateFloat32ToInt32: | |
342 case IrOpcode::kTruncateFloat32ToUint32: | |
343 case IrOpcode::kBitcastFloat32ToInt32: | |
344 MACHINE_FLOAT32_UNOP_LIST(LABEL) { | |
345 CheckValueInputForFloat32Op(node, 0); | |
346 } | |
347 break; | |
348 case IrOpcode::kFloat64Equal: | |
349 case IrOpcode::kFloat64LessThan: | |
350 case IrOpcode::kFloat64LessThanOrEqual: | |
351 MACHINE_FLOAT64_BINOP_LIST(LABEL) { | |
352 CheckValueInputForFloat64Op(node, 0); | |
353 CheckValueInputForFloat64Op(node, 1); | |
354 } | |
355 break; | |
356 case IrOpcode::kFloat64SilenceNaN: | |
357 MACHINE_FLOAT64_UNOP_LIST(LABEL) { | |
358 CheckValueInputForFloat64Op(node, 0); | |
359 } | |
360 break; | |
361 #undef LABEL | |
362 case IrOpcode::kParameter: | |
363 case IrOpcode::kProjection: | |
364 break; | |
365 case IrOpcode::kLoad: | |
366 case IrOpcode::kAtomicLoad: | |
367 CheckValueInputIsTaggedOrPointer(node, 0); | |
368 CheckValueInputRepresentationIs( | |
369 node, 1, MachineType::PointerRepresentation()); | |
370 break; | |
371 case IrOpcode::kStore: | |
372 CheckValueInputIsTaggedOrPointer(node, 0); | |
373 CheckValueInputRepresentationIs( | |
374 node, 1, MachineType::PointerRepresentation()); | |
375 switch (StoreRepresentationOf(node->op()).representation()) { | |
376 case MachineRepresentation::kTagged: | |
377 case MachineRepresentation::kTaggedPointer: | |
378 case MachineRepresentation::kTaggedSigned: | |
379 CheckValueInputIsTagged(node, 2); | |
380 break; | |
381 default: | |
382 CheckValueInputRepresentationIs( | |
383 node, 2, | |
384 StoreRepresentationOf(node->op()).representation()); | |
385 } | |
386 break; | |
387 case IrOpcode::kAtomicStore: | |
388 CheckValueInputIsTaggedOrPointer(node, 0); | |
389 CheckValueInputRepresentationIs( | |
390 node, 1, MachineType::PointerRepresentation()); | |
391 switch (AtomicStoreRepresentationOf(node->op())) { | |
392 case MachineRepresentation::kTagged: | |
393 case MachineRepresentation::kTaggedPointer: | |
394 case MachineRepresentation::kTaggedSigned: | |
395 CheckValueInputIsTagged(node, 2); | |
396 break; | |
397 default: | |
398 CheckValueInputRepresentationIs( | |
399 node, 2, AtomicStoreRepresentationOf(node->op())); | |
400 } | |
401 break; | |
402 case IrOpcode::kPhi: | |
403 switch (typer_->GetRepresentation(node)) { | |
404 case MachineRepresentation::kTagged: | |
405 case MachineRepresentation::kTaggedPointer: | |
406 case MachineRepresentation::kTaggedSigned: | |
407 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { | |
408 CheckValueInputIsTagged(node, i); | |
409 } | |
410 break; | |
411 default: | |
412 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { | |
413 CheckValueInputRepresentationIs( | |
414 node, i, typer_->GetRepresentation(node)); | |
415 } | |
416 break; | |
417 } | |
418 break; | |
419 case IrOpcode::kBranch: | |
420 case IrOpcode::kSwitch: | |
421 CheckValueInputForInt32Op(node, 0); | |
422 break; | |
423 case IrOpcode::kReturn: | |
424 // TODO(epertoso): use the linkage to determine which tipe we | |
425 // should have here. | |
426 break; | |
427 case IrOpcode::kTypedStateValues: | |
428 case IrOpcode::kFrameState: | |
429 break; | |
430 default: | |
431 if (node->op()->ValueInputCount() != 0) { | |
432 std::stringstream str; | |
433 str << "Node #" << node->id() << ":" << *node->op() | |
434 << " in the machine graph is not being checked."; | |
435 FATAL(str.str().c_str()); | |
436 } | |
437 break; | |
438 } | |
439 } | |
440 } | |
441 } | |
442 | |
443 private: | |
444 void CheckValueInputRepresentationIs(Node const* node, int index, | |
445 MachineRepresentation representation) { | |
446 Node const* input = node->InputAt(index); | |
447 if (typer_->GetRepresentation(input) != representation) { | |
448 std::stringstream str; | |
449 str << "TypeError: node #" << node->id() << ":" << *node->op() | |
450 << " uses node #" << input->id() << ":" << *input->op() | |
451 << " which doesn't have a " << MachineReprToString(representation) | |
452 << " representation."; | |
453 FATAL(str.str().c_str()); | |
454 } | |
455 } | |
456 | |
457 void CheckValueInputIsTagged(Node const* node, int index) { | |
458 Node const* input = node->InputAt(index); | |
459 switch (typer_->GetRepresentation(input)) { | |
460 case MachineRepresentation::kTagged: | |
461 case MachineRepresentation::kTaggedPointer: | |
462 case MachineRepresentation::kTaggedSigned: | |
463 return; | |
464 default: | |
465 break; | |
466 } | |
467 std::ostringstream str; | |
468 str << "TypeError: node #" << node->id() << ":" << *node->op() | |
469 << " uses node #" << input->id() << ":" << *input->op() | |
470 << " which doesn't have a tagged representation."; | |
471 FATAL(str.str().c_str()); | |
472 } | |
473 | |
474 void CheckValueInputIsTaggedOrPointer(Node const* node, int index) { | |
475 Node const* input = node->InputAt(index); | |
476 switch (typer_->GetRepresentation(input)) { | |
477 case MachineRepresentation::kTagged: | |
478 case MachineRepresentation::kTaggedPointer: | |
479 case MachineRepresentation::kTaggedSigned: | |
480 return; | |
481 default: | |
482 break; | |
483 } | |
484 if (typer_->GetRepresentation(input) != | |
485 MachineType::PointerRepresentation()) { | |
486 std::ostringstream str; | |
487 str << "TypeError: node #" << node->id() << ":" << *node->op() | |
488 << " uses node #" << input->id() << ":" << *input->op() | |
489 << " which doesn't have a tagged or pointer representation."; | |
490 FATAL(str.str().c_str()); | |
491 } | |
492 } | |
493 | |
494 void CheckValueInputForInt32Op(Node const* node, int index) { | |
495 Node const* input = node->InputAt(index); | |
496 switch (typer_->GetRepresentation(input)) { | |
497 case MachineRepresentation::kBit: | |
498 case MachineRepresentation::kWord8: | |
499 case MachineRepresentation::kWord16: | |
500 case MachineRepresentation::kWord32: | |
501 return; | |
502 case MachineRepresentation::kNone: { | |
503 std::ostringstream str; | |
504 str << "TypeError: node #" << input->id() << ":" << *input->op() | |
505 << " is untyped."; | |
506 FATAL(str.str().c_str()); | |
507 break; | |
508 } | |
509 default: | |
510 break; | |
511 } | |
512 std::ostringstream str; | |
513 str << "TypeError: node #" << node->id() << ":" << *node->op() | |
514 << " uses node #" << input->id() << ":" << *input->op() | |
515 << " which doesn't have an int32-compatible representation."; | |
516 FATAL(str.str().c_str()); | |
517 } | |
518 | |
519 void CheckValueInputForInt64Op(Node const* node, int index) { | |
520 Node const* input = node->InputAt(index); | |
521 switch (typer_->GetRepresentation(input)) { | |
522 case MachineRepresentation::kWord64: | |
523 return; | |
524 case MachineRepresentation::kNone: { | |
525 std::ostringstream str; | |
526 str << "TypeError: node #" << input->id() << ":" << *input->op() | |
527 << " is untyped."; | |
528 FATAL(str.str().c_str()); | |
529 break; | |
530 } | |
531 | |
532 default: | |
533 break; | |
534 } | |
535 std::ostringstream str; | |
536 str << "TypeError: node #" << node->id() << ":" << *node->op() | |
537 << " uses node #" << input->id() << ":" << *input->op() | |
538 << " which doesn't have a kWord64 representation."; | |
539 FATAL(str.str().c_str()); | |
540 } | |
541 | |
542 void CheckValueInputForFloat32Op(Node const* node, int index) { | |
543 Node const* input = node->InputAt(index); | |
544 if (MachineRepresentation::kFloat32 == typer_->GetRepresentation(input)) { | |
545 return; | |
546 } | |
547 std::ostringstream str; | |
548 str << "TypeError: node #" << node->id() << ":" << *node->op() | |
549 << " uses node #" << input->id() << ":" << *input->op() | |
550 << " which doesn't have a kFloat32 representation."; | |
551 FATAL(str.str().c_str()); | |
552 } | |
553 | |
554 void CheckValueInputForFloat64Op(Node const* node, int index) { | |
555 Node const* input = node->InputAt(index); | |
556 if (MachineRepresentation::kFloat64 == typer_->GetRepresentation(input)) { | |
557 return; | |
558 } | |
559 std::ostringstream str; | |
560 str << "TypeError: node #" << node->id() << ":" << *node->op() | |
561 << " uses node #" << input->id() << ":" << *input->op() | |
562 << " which doesn't have a kFloat64 representation."; | |
563 FATAL(str.str().c_str()); | |
564 } | |
565 | |
566 void CheckCallInputs(Node const* node) { | |
567 CallDescriptor const* desc = CallDescriptorOf(node->op()); | |
568 std::ostringstream str; | |
569 bool should_log_error = false; | |
570 for (size_t i = 0; i < desc->InputCount(); ++i) { | |
571 Node const* input = node->InputAt(static_cast<int>(i)); | |
572 MachineRepresentation const input_type = typer_->GetRepresentation(input); | |
573 MachineRepresentation const expected_input_type = | |
574 desc->GetInputType(i).representation(); | |
575 if (!IsCompatible(expected_input_type, input_type)) { | |
576 if (!should_log_error) { | |
577 should_log_error = true; | |
578 str << "TypeError: node #" << node->id() << ":" << *node->op() | |
579 << " has wrong type for:" << std::endl; | |
580 } else { | |
581 str << std::endl; | |
582 } | |
583 str << " * input " << i << " (" << input->id() << ":" << *input->op() | |
584 << ") doesn't have a " << MachineReprToString(expected_input_type) | |
585 << " representation."; | |
586 } | |
587 } | |
588 if (should_log_error) { | |
589 FATAL(str.str().c_str()); | |
590 } | |
591 } | |
592 | |
593 bool Intersect(MachineRepresentation lhs, MachineRepresentation rhs) { | |
594 return (GetRepresentationProperties(lhs) & | |
595 GetRepresentationProperties(rhs)) != 0; | |
596 } | |
597 | |
598 enum RepresentationProperties { kIsPointer = 1, kIsTagged = 2 }; | |
599 | |
600 int GetRepresentationProperties(MachineRepresentation representation) { | |
601 switch (representation) { | |
602 case MachineRepresentation::kTagged: | |
603 case MachineRepresentation::kTaggedPointer: | |
604 return kIsPointer | kIsTagged; | |
605 case MachineRepresentation::kTaggedSigned: | |
606 return kIsTagged; | |
607 case MachineRepresentation::kWord32: | |
608 return MachineRepresentation::kWord32 == | |
609 MachineType::PointerRepresentation() | |
610 ? kIsPointer | |
611 : 0; | |
612 case MachineRepresentation::kWord64: | |
613 return MachineRepresentation::kWord64 == | |
614 MachineType::PointerRepresentation() | |
615 ? kIsPointer | |
616 : 0; | |
617 default: | |
618 return 0; | |
619 } | |
620 } | |
621 | |
622 bool IsCompatible(MachineRepresentation expected, | |
623 MachineRepresentation actual) { | |
624 switch (expected) { | |
625 case MachineRepresentation::kTagged: | |
626 return (actual == MachineRepresentation::kTagged || | |
627 actual == MachineRepresentation::kTaggedSigned || | |
628 actual == MachineRepresentation::kTaggedPointer); | |
629 case MachineRepresentation::kTaggedSigned: | |
630 case MachineRepresentation::kTaggedPointer: | |
631 case MachineRepresentation::kFloat32: | |
632 case MachineRepresentation::kFloat64: | |
633 case MachineRepresentation::kSimd128: | |
634 case MachineRepresentation::kBit: | |
635 case MachineRepresentation::kWord8: | |
636 case MachineRepresentation::kWord16: | |
637 case MachineRepresentation::kWord64: | |
638 return expected == actual; | |
639 break; | |
640 case MachineRepresentation::kWord32: | |
641 return (actual == MachineRepresentation::kBit || | |
642 actual == MachineRepresentation::kWord8 || | |
643 actual == MachineRepresentation::kWord16 || | |
644 actual == MachineRepresentation::kWord32); | |
645 case MachineRepresentation::kNone: | |
646 UNREACHABLE(); | |
647 } | |
648 return false; | |
649 } | |
650 | |
651 Schedule const* const schedule_; | |
652 MachineRepresentationInferrer const* const typer_; | |
653 }; | |
654 | |
655 } // namespace | |
656 | |
657 void MachineGraphVerifier::Run(Graph* graph, Schedule const* const schedule, | |
658 Linkage* linkage, Zone* temp_zone) { | |
659 MachineRepresentationInferrer representation_inferrer(schedule, graph, | |
660 linkage, temp_zone); | |
661 MachineRepresentationChecker checker(schedule, &representation_inferrer); | |
662 checker.Run(); | |
663 } | |
664 | |
665 } // namespace compiler | |
666 } // namespace internal | |
667 } // namespace v8 | |
OLD | NEW |