• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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