1 // Copyright 2022 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 #ifndef V8_MAGLEV_MAGLEV_GRAPH_VERIFIER_H_ 6 #define V8_MAGLEV_MAGLEV_GRAPH_VERIFIER_H_ 7 8 #include "src/maglev/maglev-graph-labeller.h" 9 #include "src/maglev/maglev-ir.h" 10 11 namespace v8 { 12 namespace internal { 13 namespace maglev { 14 15 std::ostream& operator<<(std::ostream& os, const ValueRepresentation& repr) { 16 switch (repr) { 17 case ValueRepresentation::kTagged: 18 os << "TaggedValue"; 19 break; 20 case ValueRepresentation::kUntagged: 21 os << "UntaggedValue"; 22 break; 23 } 24 return os; 25 } 26 27 class Graph; 28 29 // TODO(victorgomes): Currently it only verifies the inputs for all ValueNodes 30 // are expected to be tagged/untagged. Add more verification later. 31 class MaglevGraphVerifier { 32 public: PreProcessGraph(MaglevCompilationUnit * compilation_unit,Graph * graph)33 void PreProcessGraph(MaglevCompilationUnit* compilation_unit, Graph* graph) { 34 if (compilation_unit->has_graph_labeller()) { 35 graph_labeller_ = compilation_unit->graph_labeller(); 36 } 37 } 38 PostProcessGraph(MaglevCompilationUnit *,Graph * graph)39 void PostProcessGraph(MaglevCompilationUnit*, Graph* graph) {} PreProcessBasicBlock(MaglevCompilationUnit *,BasicBlock * block)40 void PreProcessBasicBlock(MaglevCompilationUnit*, BasicBlock* block) {} 41 CheckValueInputIs(NodeBase * node,int i,ValueRepresentation repr)42 void CheckValueInputIs(NodeBase* node, int i, ValueRepresentation repr) { 43 ValueNode* input = node->input(i).node(); 44 if (input->value_representation() != repr) { 45 std::ostringstream str; 46 str << "Type representation error: node "; 47 if (graph_labeller_) { 48 str << "#" << graph_labeller_->NodeId(node) << " : "; 49 } 50 str << node->opcode() << " (input @" << i << " = " << input->opcode() 51 << ") type " << input->value_representation() << " is not " << repr; 52 FATAL("%s", str.str().c_str()); 53 } 54 } 55 Process(NodeBase * node,const ProcessingState & state)56 void Process(NodeBase* node, const ProcessingState& state) { 57 switch (node->opcode()) { 58 case Opcode::kConstant: 59 case Opcode::kSmiConstant: 60 case Opcode::kInt32Constant: 61 case Opcode::kRootConstant: 62 case Opcode::kInitialValue: 63 case Opcode::kRegisterInput: 64 case Opcode::kGapMove: 65 case Opcode::kDeopt: 66 case Opcode::kJump: 67 case Opcode::kJumpLoop: 68 // No input. 69 DCHECK_EQ(node->input_count(), 0); 70 break; 71 case Opcode::kGenericNegate: 72 case Opcode::kGenericIncrement: 73 case Opcode::kGenericDecrement: 74 case Opcode::kCheckedSmiUntag: 75 case Opcode::kLoadField: 76 case Opcode::kLoadGlobal: 77 // TODO(victorgomes): Can we check that the input is actually a map? 78 case Opcode::kCheckMaps: 79 // TODO(victorgomes): Can we check that the input is Boolean? 80 case Opcode::kBranchIfTrue: 81 case Opcode::kBranchIfToBooleanTrue: 82 case Opcode::kReturn: 83 // Generic tagged unary operations. 84 DCHECK_EQ(node->input_count(), 1); 85 CheckValueInputIs(node, 0, ValueRepresentation::kTagged); 86 break; 87 case Opcode::kCheckedSmiTag: 88 // Untagged unary operations. 89 CheckValueInputIs(node, 0, ValueRepresentation::kUntagged); 90 break; 91 case Opcode::kGenericAdd: 92 case Opcode::kGenericSubtract: 93 case Opcode::kGenericMultiply: 94 case Opcode::kGenericDivide: 95 case Opcode::kGenericModulus: 96 case Opcode::kGenericExponentiate: 97 case Opcode::kGenericBitwiseAnd: 98 case Opcode::kGenericBitwiseOr: 99 case Opcode::kGenericBitwiseXor: 100 case Opcode::kGenericShiftLeft: 101 case Opcode::kGenericShiftRight: 102 case Opcode::kGenericShiftRightLogical: 103 case Opcode::kGenericBitwiseNot: 104 // TODO(victorgomes): Can we use the fact that these nodes return a 105 // Boolean? 106 case Opcode::kGenericEqual: 107 case Opcode::kGenericStrictEqual: 108 case Opcode::kGenericLessThan: 109 case Opcode::kGenericLessThanOrEqual: 110 case Opcode::kGenericGreaterThan: 111 case Opcode::kGenericGreaterThanOrEqual: 112 // TODO(victorgomes): Can we check that first input is an Object? 113 case Opcode::kStoreField: 114 case Opcode::kLoadNamedGeneric: 115 // Generic tagged binary operations. 116 DCHECK_EQ(node->input_count(), 2); 117 CheckValueInputIs(node, 0, ValueRepresentation::kTagged); 118 CheckValueInputIs(node, 1, ValueRepresentation::kTagged); 119 break; 120 case Opcode::kInt32AddWithOverflow: 121 // Untagged binary operations. 122 CheckValueInputIs(node, 0, ValueRepresentation::kUntagged); 123 CheckValueInputIs(node, 1, ValueRepresentation::kUntagged); 124 break; 125 case Opcode::kCall: 126 case Opcode::kPhi: 127 // All inputs should be tagged. 128 for (int i = 0; i < node->input_count(); i++) { 129 CheckValueInputIs(node, i, ValueRepresentation::kTagged); 130 } 131 break; 132 } 133 } 134 135 private: 136 MaglevGraphLabeller* graph_labeller_ = nullptr; 137 }; 138 139 } // namespace maglev 140 } // namespace internal 141 } // namespace v8 142 143 #endif // V8_MAGLEV_MAGLEV_GRAPH_VERIFIER_H_ 144