Chromium Code Reviews| 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 |