Index: src/compiler/machine-graph-verifier.cc |
diff --git a/src/compiler/machine-graph-verifier.cc b/src/compiler/machine-graph-verifier.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d33ee4ec28d989e96c4195369fcb710b875ff5a9 |
--- /dev/null |
+++ b/src/compiler/machine-graph-verifier.cc |
@@ -0,0 +1,667 @@ |
+// Copyright 2016 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "src/compiler/machine-graph-verifier.h" |
+ |
+#include "src/compiler/common-operator.h" |
+#include "src/compiler/graph.h" |
+#include "src/compiler/linkage.h" |
+#include "src/compiler/machine-operator.h" |
+#include "src/compiler/node-properties.h" |
+#include "src/compiler/node.h" |
+#include "src/compiler/schedule.h" |
+#include "src/zone/zone.h" |
+ |
+namespace v8 { |
+namespace internal { |
+namespace compiler { |
+ |
+namespace { |
+ |
+class MachineRepresentationInferrer { |
+ public: |
+ MachineRepresentationInferrer(Schedule const* schedule, Graph const* graph, |
+ Linkage* linkage, Zone* zone) |
+ : schedule_(schedule), |
+ linkage_(linkage), |
+ representation_vector_(graph->NodeCount(), zone) { |
Jarin
2016/10/05 08:16:17
Explicit initialization with MachineRepresentation
|
+ Run(); |
+ } |
+ |
+ MachineRepresentation GetRepresentation(Node const* node) const { |
+ return representation_vector_.at(node->id()); |
+ } |
+ |
+ private: |
+ MachineRepresentation GetProjectionType(Node const* projection) { |
+ size_t index = ProjectionIndexOf(projection->op()); |
+ Node* input = projection->InputAt(0); |
+ switch (input->opcode()) { |
+ case IrOpcode::kInt32AddWithOverflow: |
+ case IrOpcode::kInt32SubWithOverflow: |
+ case IrOpcode::kInt32MulWithOverflow: |
+ CHECK_LE(index, static_cast<size_t>(1)); |
+ return index == 0 ? MachineRepresentation::kWord32 |
+ : MachineRepresentation::kBit; |
+ case IrOpcode::kInt64AddWithOverflow: |
+ case IrOpcode::kInt64SubWithOverflow: |
+ CHECK_LE(index, static_cast<size_t>(1)); |
+ return index == 0 ? MachineRepresentation::kWord64 |
+ : MachineRepresentation::kBit; |
+ case IrOpcode::kTryTruncateFloat32ToInt64: |
+ case IrOpcode::kTryTruncateFloat64ToInt64: |
+ case IrOpcode::kTryTruncateFloat32ToUint64: |
+ case IrOpcode::kTryTruncateFloat64ToUint64: |
+ CHECK_LE(index, static_cast<size_t>(1)); |
+ return index == 0 ? MachineRepresentation::kWord64 |
+ : MachineRepresentation::kBit; |
+ case IrOpcode::kCall: { |
+ CallDescriptor const* desc = CallDescriptorOf(input->op()); |
+ return desc->GetReturnType(index).representation(); |
+ } |
+ default: |
+ return MachineRepresentation::kNone; |
+ } |
+ } |
+ |
+ void Run() { |
+ auto blocks = schedule_->all_blocks(); |
+ for (BasicBlock* block : *blocks) { |
+ for (size_t i = 0; i <= block->NodeCount(); ++i) { |
+ Node const* node = |
+ i < block->NodeCount() ? block->NodeAt(i) : block->control_input(); |
+ if (node == nullptr) { |
+ DCHECK_EQ(block->NodeCount(), i); |
+ break; |
+ } |
+ switch (node->opcode()) { |
+ case IrOpcode::kParameter: |
+ representation_vector_[node->id()] = |
+ linkage_->GetParameterType(ParameterIndexOf(node->op())) |
+ .representation(); |
+ break; |
+ case IrOpcode::kProjection: { |
+ representation_vector_[node->id()] = GetProjectionType(node); |
+ } break; |
+ case IrOpcode::kTypedStateValues: |
+ representation_vector_[node->id()] = MachineRepresentation::kNone; |
+ break; |
+ case IrOpcode::kAtomicLoad: |
+ case IrOpcode::kLoad: |
+ case IrOpcode::kProtectedLoad: |
+ representation_vector_[node->id()] = |
+ LoadRepresentationOf(node->op()).representation(); |
+ break; |
+ case IrOpcode::kCheckedLoad: |
+ representation_vector_[node->id()] = |
+ CheckedLoadRepresentationOf(node->op()).representation(); |
+ break; |
+ case IrOpcode::kLoadStackPointer: |
+ case IrOpcode::kLoadFramePointer: |
+ case IrOpcode::kLoadParentFramePointer: |
+ representation_vector_[node->id()] = |
+ MachineType::PointerRepresentation(); |
+ break; |
+ case IrOpcode::kPhi: |
+ representation_vector_[node->id()] = |
+ PhiRepresentationOf(node->op()); |
+ break; |
+ case IrOpcode::kCall: { |
+ CallDescriptor const* desc = CallDescriptorOf(node->op()); |
+ if (desc->ReturnCount() > 0) { |
+ representation_vector_[node->id()] = |
+ desc->GetReturnType(0).representation(); |
+ } else { |
+ representation_vector_[node->id()] = |
+ MachineRepresentation::kTagged; |
+ } |
+ break; |
+ } |
+ case IrOpcode::kUnalignedLoad: |
+ representation_vector_[node->id()] = |
+ UnalignedLoadRepresentationOf(node->op()).representation(); |
+ break; |
+ case IrOpcode::kHeapConstant: |
+ case IrOpcode::kNumberConstant: |
+ case IrOpcode::kChangeBitToTagged: |
+ case IrOpcode::kIfException: |
+ case IrOpcode::kOsrValue: |
+ case IrOpcode::kChangeInt32ToTagged: |
+ case IrOpcode::kChangeUint32ToTagged: |
+ case IrOpcode::kBitcastWordToTagged: |
+ representation_vector_[node->id()] = MachineRepresentation::kTagged; |
+ break; |
+ case IrOpcode::kExternalConstant: |
+ representation_vector_[node->id()] = |
+ MachineType::PointerRepresentation(); |
+ break; |
+ case IrOpcode::kBitcastTaggedToWord: |
+ representation_vector_[node->id()] = |
+ MachineType::PointerRepresentation(); |
+ break; |
+ case IrOpcode::kBitcastWordToTaggedSigned: |
+ representation_vector_[node->id()] = |
+ MachineRepresentation::kTaggedSigned; |
+ break; |
+ case IrOpcode::kWord32Equal: |
+ case IrOpcode::kInt32LessThan: |
+ case IrOpcode::kInt32LessThanOrEqual: |
+ case IrOpcode::kUint32LessThan: |
+ case IrOpcode::kUint32LessThanOrEqual: |
+ case IrOpcode::kWord64Equal: |
+ case IrOpcode::kInt64LessThan: |
+ case IrOpcode::kInt64LessThanOrEqual: |
+ case IrOpcode::kUint64LessThan: |
+ case IrOpcode::kUint64LessThanOrEqual: |
+ case IrOpcode::kFloat32Equal: |
+ case IrOpcode::kFloat32LessThan: |
+ case IrOpcode::kFloat32LessThanOrEqual: |
+ case IrOpcode::kFloat64Equal: |
+ case IrOpcode::kFloat64LessThan: |
+ case IrOpcode::kFloat64LessThanOrEqual: |
+ case IrOpcode::kChangeTaggedToBit: |
+ representation_vector_[node->id()] = MachineRepresentation::kBit; |
+ break; |
+#define LABEL(opcode) case IrOpcode::k##opcode: |
+ case IrOpcode::kTruncateInt64ToInt32: |
+ case IrOpcode::kTruncateFloat32ToInt32: |
+ case IrOpcode::kTruncateFloat32ToUint32: |
+ case IrOpcode::kBitcastFloat32ToInt32: |
+ case IrOpcode::kInt32x4ExtractLane: |
+ case IrOpcode::kInt32Constant: |
+ case IrOpcode::kRelocatableInt32Constant: |
+ case IrOpcode::kTruncateFloat64ToWord32: |
+ case IrOpcode::kTruncateFloat64ToUint32: |
+ case IrOpcode::kChangeFloat64ToInt32: |
+ case IrOpcode::kChangeFloat64ToUint32: |
+ case IrOpcode::kRoundFloat64ToInt32: |
+ case IrOpcode::kFloat64ExtractLowWord32: |
+ case IrOpcode::kFloat64ExtractHighWord32: |
+ MACHINE_UNOP_32_LIST(LABEL) |
+ MACHINE_BINOP_32_LIST(LABEL) { |
+ representation_vector_[node->id()] = |
+ MachineRepresentation::kWord32; |
+ } |
+ break; |
+ case IrOpcode::kChangeInt32ToInt64: |
+ case IrOpcode::kChangeUint32ToUint64: |
+ case IrOpcode::kInt64Constant: |
+ case IrOpcode::kRelocatableInt64Constant: |
+ case IrOpcode::kBitcastFloat64ToInt64: |
+ MACHINE_BINOP_64_LIST(LABEL) { |
+ representation_vector_[node->id()] = |
+ MachineRepresentation::kWord64; |
+ } |
+ break; |
+ case IrOpcode::kRoundInt32ToFloat32: |
+ case IrOpcode::kRoundUint32ToFloat32: |
+ case IrOpcode::kRoundInt64ToFloat32: |
+ case IrOpcode::kRoundUint64ToFloat32: |
+ case IrOpcode::kFloat32Constant: |
+ case IrOpcode::kTruncateFloat64ToFloat32: |
+ MACHINE_FLOAT32_BINOP_LIST(LABEL) |
+ MACHINE_FLOAT32_UNOP_LIST(LABEL) { |
+ representation_vector_[node->id()] = |
+ MachineRepresentation::kFloat32; |
+ } |
+ break; |
+ case IrOpcode::kRoundInt64ToFloat64: |
+ case IrOpcode::kRoundUint64ToFloat64: |
+ case IrOpcode::kChangeFloat32ToFloat64: |
+ case IrOpcode::kChangeInt32ToFloat64: |
+ case IrOpcode::kChangeUint32ToFloat64: |
+ case IrOpcode::kFloat64Constant: |
+ case IrOpcode::kFloat64SilenceNaN: |
+ MACHINE_FLOAT64_BINOP_LIST(LABEL) |
+ MACHINE_FLOAT64_UNOP_LIST(LABEL) { |
+ representation_vector_[node->id()] = |
+ MachineRepresentation::kFloat64; |
+ } |
+ break; |
+#undef LABEL |
+ default: |
+ break; |
Jarin
2016/10/05 08:16:17
As discussed offline, it could be nicer to have a
|
+ } |
+ } |
+ } |
+ } |
+ |
+ Schedule const* const schedule_; |
+ Linkage const* const linkage_; |
+ ZoneVector<MachineRepresentation> representation_vector_; |
+}; |
+ |
+class MachineRepresentationChecker { |
+ public: |
+ MachineRepresentationChecker(Schedule const* const schedule, |
+ MachineRepresentationInferrer const* const typer) |
+ : schedule_(schedule), typer_(typer) {} |
+ |
+ void Run() { |
+ BasicBlockVector const* blocks = schedule_->all_blocks(); |
+ for (BasicBlock* block : *blocks) { |
+ for (size_t i = 0; i <= block->NodeCount(); ++i) { |
+ Node const* node = |
+ i < block->NodeCount() ? block->NodeAt(i) : block->control_input(); |
+ if (node == nullptr) { |
+ DCHECK_EQ(block->NodeCount(), i); |
+ break; |
+ } |
+ switch (node->opcode()) { |
+ case IrOpcode::kCall: |
+ case IrOpcode::kTailCall: |
+ CheckCallInputs(node); |
+ break; |
+ case IrOpcode::kChangeBitToTagged: |
+ CHECK_EQ(MachineRepresentation::kBit, |
+ typer_->GetRepresentation(node->InputAt(0))); |
+ break; |
+ case IrOpcode::kChangeTaggedToBit: |
+ CHECK_EQ(MachineRepresentation::kTagged, |
+ typer_->GetRepresentation(node->InputAt(0))); |
+ break; |
+ case IrOpcode::kRoundInt64ToFloat64: |
+ case IrOpcode::kRoundUint64ToFloat64: |
+ case IrOpcode::kRoundInt64ToFloat32: |
+ case IrOpcode::kRoundUint64ToFloat32: |
+ case IrOpcode::kTruncateInt64ToInt32: |
+ CheckValueInputForInt64Op(node, 0); |
+ break; |
+ case IrOpcode::kBitcastWordToTagged: |
+ case IrOpcode::kBitcastWordToTaggedSigned: |
+ CheckValueInputRepresentationIs( |
+ node, 0, MachineType::PointerRepresentation()); |
+ break; |
+ case IrOpcode::kBitcastTaggedToWord: |
+ CheckValueInputIsTagged(node, 0); |
+ break; |
+ case IrOpcode::kTruncateFloat64ToWord32: |
+ case IrOpcode::kTruncateFloat64ToUint32: |
+ case IrOpcode::kTruncateFloat64ToFloat32: |
+ case IrOpcode::kChangeFloat64ToInt32: |
+ case IrOpcode::kChangeFloat64ToUint32: |
+ case IrOpcode::kRoundFloat64ToInt32: |
+ case IrOpcode::kFloat64ExtractLowWord32: |
+ case IrOpcode::kFloat64ExtractHighWord32: |
+ case IrOpcode::kBitcastFloat64ToInt64: |
+ CheckValueInputForFloat64Op(node, 0); |
+ break; |
+ case IrOpcode::kWord64Equal: |
+ CheckValueInputIsTaggedOrPointer(node, 0); |
+ CheckValueInputRepresentationIs( |
+ node, 1, typer_->GetRepresentation(node->InputAt(0))); |
+ break; |
+ case IrOpcode::kInt64LessThan: |
+ case IrOpcode::kInt64LessThanOrEqual: |
+ case IrOpcode::kUint64LessThan: |
+ case IrOpcode::kUint64LessThanOrEqual: |
+ CheckValueInputForInt64Op(node, 0); |
+ CheckValueInputForInt64Op(node, 1); |
+ break; |
+ case IrOpcode::kInt32x4ExtractLane: |
+ CheckValueInputRepresentationIs(node, 0, |
+ MachineRepresentation::kSimd128); |
+ break; |
+#define LABEL(opcode) case IrOpcode::k##opcode: |
+ case IrOpcode::kChangeInt32ToTagged: |
+ case IrOpcode::kChangeUint32ToTagged: |
+ case IrOpcode::kChangeInt32ToFloat64: |
+ case IrOpcode::kChangeUint32ToFloat64: |
+ case IrOpcode::kRoundInt32ToFloat32: |
+ case IrOpcode::kRoundUint32ToFloat32: |
+ case IrOpcode::kChangeInt32ToInt64: |
+ case IrOpcode::kChangeUint32ToUint64: |
+ MACHINE_UNOP_32_LIST(LABEL) { CheckValueInputForInt32Op(node, 0); } |
+ break; |
+ case IrOpcode::kWord32Equal: |
+ case IrOpcode::kInt32LessThan: |
+ case IrOpcode::kInt32LessThanOrEqual: |
+ case IrOpcode::kUint32LessThan: |
+ case IrOpcode::kUint32LessThanOrEqual: |
+ MACHINE_BINOP_32_LIST(LABEL) { |
+ CheckValueInputForInt32Op(node, 0); |
+ CheckValueInputForInt32Op(node, 1); |
+ } |
+ break; |
+ MACHINE_BINOP_64_LIST(LABEL) { |
+ CheckValueInputForInt64Op(node, 0); |
+ CheckValueInputForInt64Op(node, 1); |
+ } |
+ break; |
+ case IrOpcode::kFloat32Equal: |
+ case IrOpcode::kFloat32LessThan: |
+ case IrOpcode::kFloat32LessThanOrEqual: |
+ MACHINE_FLOAT32_BINOP_LIST(LABEL) { |
+ CheckValueInputForFloat32Op(node, 0); |
+ CheckValueInputForFloat32Op(node, 1); |
+ } |
+ break; |
+ case IrOpcode::kChangeFloat32ToFloat64: |
+ case IrOpcode::kTruncateFloat32ToInt32: |
+ case IrOpcode::kTruncateFloat32ToUint32: |
+ case IrOpcode::kBitcastFloat32ToInt32: |
+ MACHINE_FLOAT32_UNOP_LIST(LABEL) { |
+ CheckValueInputForFloat32Op(node, 0); |
+ } |
+ break; |
+ case IrOpcode::kFloat64Equal: |
+ case IrOpcode::kFloat64LessThan: |
+ case IrOpcode::kFloat64LessThanOrEqual: |
+ MACHINE_FLOAT64_BINOP_LIST(LABEL) { |
+ CheckValueInputForFloat64Op(node, 0); |
+ CheckValueInputForFloat64Op(node, 1); |
+ } |
+ break; |
+ case IrOpcode::kFloat64SilenceNaN: |
+ MACHINE_FLOAT64_UNOP_LIST(LABEL) { |
+ CheckValueInputForFloat64Op(node, 0); |
+ } |
+ break; |
+#undef LABEL |
+ case IrOpcode::kParameter: |
+ case IrOpcode::kProjection: |
+ break; |
+ case IrOpcode::kLoad: |
+ case IrOpcode::kAtomicLoad: |
+ CheckValueInputIsTaggedOrPointer(node, 0); |
+ CheckValueInputRepresentationIs( |
+ node, 1, MachineType::PointerRepresentation()); |
+ break; |
+ case IrOpcode::kStore: |
+ CheckValueInputIsTaggedOrPointer(node, 0); |
+ CheckValueInputRepresentationIs( |
+ node, 1, MachineType::PointerRepresentation()); |
+ switch (StoreRepresentationOf(node->op()).representation()) { |
+ case MachineRepresentation::kTagged: |
+ case MachineRepresentation::kTaggedPointer: |
+ case MachineRepresentation::kTaggedSigned: |
+ CheckValueInputIsTagged(node, 2); |
+ break; |
+ default: |
+ CheckValueInputRepresentationIs( |
+ node, 2, |
+ StoreRepresentationOf(node->op()).representation()); |
+ } |
+ break; |
+ case IrOpcode::kAtomicStore: |
+ CheckValueInputIsTaggedOrPointer(node, 0); |
+ CheckValueInputRepresentationIs( |
+ node, 1, MachineType::PointerRepresentation()); |
+ switch (AtomicStoreRepresentationOf(node->op())) { |
+ case MachineRepresentation::kTagged: |
+ case MachineRepresentation::kTaggedPointer: |
+ case MachineRepresentation::kTaggedSigned: |
+ CheckValueInputIsTagged(node, 2); |
+ break; |
+ default: |
+ CheckValueInputRepresentationIs( |
+ node, 2, AtomicStoreRepresentationOf(node->op())); |
+ } |
+ break; |
+ case IrOpcode::kPhi: |
+ switch (typer_->GetRepresentation(node)) { |
+ case MachineRepresentation::kTagged: |
+ case MachineRepresentation::kTaggedPointer: |
+ case MachineRepresentation::kTaggedSigned: |
+ for (int i = 0; i < node->op()->ValueInputCount(); ++i) { |
+ CheckValueInputIsTagged(node, i); |
+ } |
+ break; |
+ default: |
+ for (int i = 0; i < node->op()->ValueInputCount(); ++i) { |
+ CheckValueInputRepresentationIs( |
+ node, i, typer_->GetRepresentation(node)); |
+ } |
+ break; |
+ } |
+ break; |
+ case IrOpcode::kBranch: |
+ case IrOpcode::kSwitch: |
+ CheckValueInputForInt32Op(node, 0); |
+ break; |
+ case IrOpcode::kReturn: |
+ // TODO(epertoso): use the linkage to determine which tipe we |
+ // should have here. |
+ break; |
+ case IrOpcode::kTypedStateValues: |
+ case IrOpcode::kFrameState: |
+ break; |
+ default: |
+ if (node->op()->ValueInputCount() != 0) { |
+ std::stringstream str; |
+ str << "Node #" << node->id() << ":" << *node->op() |
+ << " in the machine graph is not being checked."; |
+ FATAL(str.str().c_str()); |
+ } |
+ break; |
+ } |
+ } |
+ } |
+ } |
+ |
+ private: |
+ void CheckValueInputRepresentationIs(Node const* node, int index, |
+ MachineRepresentation representation) { |
+ Node const* input = node->InputAt(index); |
+ if (typer_->GetRepresentation(input) != representation) { |
+ std::stringstream str; |
+ str << "TypeError: node #" << node->id() << ":" << *node->op() |
+ << " uses node #" << input->id() << ":" << *input->op() |
+ << " which doesn't have a " << MachineReprToString(representation) |
+ << " representation."; |
+ FATAL(str.str().c_str()); |
+ } |
+ } |
+ |
+ void CheckValueInputIsTagged(Node const* node, int index) { |
+ Node const* input = node->InputAt(index); |
+ switch (typer_->GetRepresentation(input)) { |
+ case MachineRepresentation::kTagged: |
+ case MachineRepresentation::kTaggedPointer: |
+ case MachineRepresentation::kTaggedSigned: |
+ return; |
+ default: |
+ break; |
+ } |
+ std::ostringstream str; |
+ str << "TypeError: node #" << node->id() << ":" << *node->op() |
+ << " uses node #" << input->id() << ":" << *input->op() |
+ << " which doesn't have a tagged representation."; |
+ FATAL(str.str().c_str()); |
+ } |
+ |
+ void CheckValueInputIsTaggedOrPointer(Node const* node, int index) { |
+ Node const* input = node->InputAt(index); |
+ switch (typer_->GetRepresentation(input)) { |
+ case MachineRepresentation::kTagged: |
+ case MachineRepresentation::kTaggedPointer: |
+ case MachineRepresentation::kTaggedSigned: |
+ return; |
+ default: |
+ break; |
+ } |
+ if (typer_->GetRepresentation(input) != |
+ MachineType::PointerRepresentation()) { |
+ std::ostringstream str; |
+ str << "TypeError: node #" << node->id() << ":" << *node->op() |
+ << " uses node #" << input->id() << ":" << *input->op() |
+ << " which doesn't have a tagged or pointer representation."; |
+ FATAL(str.str().c_str()); |
+ } |
+ } |
+ |
+ void CheckValueInputForInt32Op(Node const* node, int index) { |
+ Node const* input = node->InputAt(index); |
+ switch (typer_->GetRepresentation(input)) { |
+ case MachineRepresentation::kBit: |
+ case MachineRepresentation::kWord8: |
+ case MachineRepresentation::kWord16: |
+ case MachineRepresentation::kWord32: |
+ return; |
+ case MachineRepresentation::kNone: { |
+ std::ostringstream str; |
+ str << "TypeError: node #" << input->id() << ":" << *input->op() |
+ << " is untyped."; |
+ FATAL(str.str().c_str()); |
+ break; |
+ } |
+ default: |
+ break; |
+ } |
+ std::ostringstream str; |
+ str << "TypeError: node #" << node->id() << ":" << *node->op() |
+ << " uses node #" << input->id() << ":" << *input->op() |
+ << " which doesn't have an int32-compatible representation."; |
+ FATAL(str.str().c_str()); |
+ } |
+ |
+ void CheckValueInputForInt64Op(Node const* node, int index) { |
+ Node const* input = node->InputAt(index); |
+ switch (typer_->GetRepresentation(input)) { |
+ case MachineRepresentation::kWord64: |
+ return; |
+ case MachineRepresentation::kNone: { |
+ std::ostringstream str; |
+ str << "TypeError: node #" << input->id() << ":" << *input->op() |
+ << " is untyped."; |
+ FATAL(str.str().c_str()); |
+ break; |
+ } |
+ |
+ default: |
+ break; |
+ } |
+ std::ostringstream str; |
+ str << "TypeError: node #" << node->id() << ":" << *node->op() |
+ << " uses node #" << input->id() << ":" << *input->op() |
+ << " which doesn't have a kWord64 representation."; |
+ FATAL(str.str().c_str()); |
+ } |
+ |
+ void CheckValueInputForFloat32Op(Node const* node, int index) { |
+ Node const* input = node->InputAt(index); |
+ if (MachineRepresentation::kFloat32 == typer_->GetRepresentation(input)) { |
+ return; |
+ } |
+ std::ostringstream str; |
+ str << "TypeError: node #" << node->id() << ":" << *node->op() |
+ << " uses node #" << input->id() << ":" << *input->op() |
+ << " which doesn't have a kFloat32 representation."; |
+ FATAL(str.str().c_str()); |
+ } |
+ |
+ void CheckValueInputForFloat64Op(Node const* node, int index) { |
+ Node const* input = node->InputAt(index); |
+ if (MachineRepresentation::kFloat64 == typer_->GetRepresentation(input)) { |
+ return; |
+ } |
+ std::ostringstream str; |
+ str << "TypeError: node #" << node->id() << ":" << *node->op() |
+ << " uses node #" << input->id() << ":" << *input->op() |
+ << " which doesn't have a kFloat64 representation."; |
+ FATAL(str.str().c_str()); |
+ } |
+ |
+ void CheckCallInputs(Node const* node) { |
+ CallDescriptor const* desc = CallDescriptorOf(node->op()); |
+ std::ostringstream str; |
+ bool should_log_error = false; |
+ for (size_t i = 0; i < desc->InputCount(); ++i) { |
+ Node const* input = node->InputAt(static_cast<int>(i)); |
+ MachineRepresentation const input_type = typer_->GetRepresentation(input); |
+ MachineRepresentation const expected_input_type = |
+ desc->GetInputType(i).representation(); |
+ if (!IsCompatible(expected_input_type, input_type)) { |
+ if (!should_log_error) { |
+ should_log_error = true; |
+ str << "TypeError: node #" << node->id() << ":" << *node->op() |
+ << " has wrong type for:" << std::endl; |
+ } else { |
+ str << std::endl; |
+ } |
+ str << " * input " << i << " (" << input->id() << ":" << *input->op() |
+ << ") doesn't have a " << MachineReprToString(expected_input_type) |
+ << " representation."; |
+ } |
+ } |
+ if (should_log_error) { |
+ FATAL(str.str().c_str()); |
+ } |
+ } |
+ |
+ bool Intersect(MachineRepresentation lhs, MachineRepresentation rhs) { |
+ return (GetRepresentationProperties(lhs) & |
+ GetRepresentationProperties(rhs)) != 0; |
+ } |
+ |
+ enum RepresentationProperties { kIsPointer = 1, kIsTagged = 2 }; |
+ |
+ int GetRepresentationProperties(MachineRepresentation representation) { |
+ switch (representation) { |
+ case MachineRepresentation::kTagged: |
+ case MachineRepresentation::kTaggedPointer: |
+ return kIsPointer | kIsTagged; |
+ case MachineRepresentation::kTaggedSigned: |
+ return kIsTagged; |
+ case MachineRepresentation::kWord32: |
+ return MachineRepresentation::kWord32 == |
+ MachineType::PointerRepresentation() |
+ ? kIsPointer |
+ : 0; |
+ case MachineRepresentation::kWord64: |
+ return MachineRepresentation::kWord64 == |
+ MachineType::PointerRepresentation() |
+ ? kIsPointer |
+ : 0; |
+ default: |
+ return 0; |
+ } |
+ } |
+ |
+ bool IsCompatible(MachineRepresentation expected, |
+ MachineRepresentation actual) { |
+ switch (expected) { |
+ case MachineRepresentation::kTagged: |
+ return (actual == MachineRepresentation::kTagged || |
+ actual == MachineRepresentation::kTaggedSigned || |
+ actual == MachineRepresentation::kTaggedPointer); |
+ case MachineRepresentation::kTaggedSigned: |
+ case MachineRepresentation::kTaggedPointer: |
+ case MachineRepresentation::kFloat32: |
+ case MachineRepresentation::kFloat64: |
+ case MachineRepresentation::kSimd128: |
+ case MachineRepresentation::kBit: |
+ case MachineRepresentation::kWord8: |
+ case MachineRepresentation::kWord16: |
+ case MachineRepresentation::kWord64: |
+ return expected == actual; |
+ break; |
+ case MachineRepresentation::kWord32: |
+ return (actual == MachineRepresentation::kBit || |
+ actual == MachineRepresentation::kWord8 || |
+ actual == MachineRepresentation::kWord16 || |
+ actual == MachineRepresentation::kWord32); |
+ case MachineRepresentation::kNone: |
+ UNREACHABLE(); |
+ } |
+ return false; |
+ } |
+ |
+ Schedule const* const schedule_; |
+ MachineRepresentationInferrer const* const typer_; |
+}; |
+ |
+} // namespace |
+ |
+void MachineGraphVerifier::Run(Graph* graph, Schedule const* const schedule, |
+ Linkage* linkage, Zone* temp_zone) { |
+ MachineRepresentationInferrer representation_inferrer(schedule, graph, |
+ linkage, temp_zone); |
+ MachineRepresentationChecker checker(schedule, &representation_inferrer); |
+ checker.Run(); |
+} |
+ |
+} // namespace compiler |
+} // namespace internal |
+} // namespace v8 |