1 | // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file |
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #ifndef RUNTIME_VM_COMPILER_BACKEND_FLOW_GRAPH_CHECKER_H_ |
6 | #define RUNTIME_VM_COMPILER_BACKEND_FLOW_GRAPH_CHECKER_H_ |
7 | |
8 | #if defined(DART_PRECOMPILED_RUNTIME) |
9 | #error "AOT runtime should not use compiler sources (including header files)" |
10 | #endif // defined(DART_PRECOMPILED_RUNTIME) |
11 | |
12 | #if defined(DEBUG) |
13 | |
14 | #include "vm/compiler/backend/flow_graph.h" |
15 | #include "vm/compiler/backend/il.h" |
16 | |
17 | namespace dart { |
18 | |
19 | // Class responsible for performing sanity checks on the flow graph. |
20 | // The intended use is running the checks after each compiler pass |
21 | // in debug mode in order to detect graph inconsistencies as soon |
22 | // as possible. This way, culprit passes are more easily identified. |
23 | // |
24 | // All important assumptions on the flow graph structure that can be |
25 | // verified in reasonable time should be made explicit in this pass |
26 | // so that we no longer rely on asserts that are dispersed throughout |
27 | // the passes or, worse, unwritten assumptions once agreed upon but |
28 | // so easily forgotten. Since the graph checker runs only in debug |
29 | // mode, it is acceptable to perform slightly elaborate tests. |
30 | class FlowGraphChecker : public FlowGraphVisitor { |
31 | public: |
32 | // Constructs graph checker. The checker uses some custom-made |
33 | // visitation to perform additional checks, and uses the |
34 | // FlowGraphVisitor structure for anything else. |
35 | explicit FlowGraphChecker(FlowGraph* flow_graph) |
36 | : FlowGraphVisitor(flow_graph->preorder()), |
37 | flow_graph_(flow_graph), |
38 | current_block_(nullptr) {} |
39 | |
40 | // Performs a sanity check on the flow graph. |
41 | void Check(const char* pass_name); |
42 | |
43 | private: |
44 | // Custom-made visitors. |
45 | void VisitBlocks() override; |
46 | void VisitInstructions(BlockEntryInstr* block); |
47 | void VisitInstruction(Instruction* instruction); |
48 | void VisitDefinition(Definition* def); |
49 | void VisitUseDef(Instruction* instruction, |
50 | Value* use, |
51 | intptr_t index, |
52 | bool is_env); |
53 | void VisitDefUse(Definition* def, Value* use, Value* prev, bool is_env); |
54 | |
55 | // Instruction visitors. |
56 | void VisitConstant(ConstantInstr* constant) override; |
57 | void VisitPhi(PhiInstr* phi) override; |
58 | void VisitGoto(GotoInstr* jmp) override; |
59 | void VisitIndirectGoto(IndirectGotoInstr* jmp) override; |
60 | void VisitBranch(BranchInstr* branch) override; |
61 | void VisitRedefinition(RedefinitionInstr* def) override; |
62 | void VisitClosureCall(ClosureCallInstr* call) override; |
63 | void VisitStaticCall(StaticCallInstr* call) override; |
64 | void VisitInstanceCall(InstanceCallInstr* call) override; |
65 | void VisitPolymorphicInstanceCall( |
66 | PolymorphicInstanceCallInstr* call) override; |
67 | |
68 | FlowGraph* const flow_graph_; |
69 | BlockEntryInstr* current_block_; |
70 | }; |
71 | |
72 | } // namespace dart |
73 | |
74 | #endif // defined(DEBUG) |
75 | |
76 | #endif // RUNTIME_VM_COMPILER_BACKEND_FLOW_GRAPH_CHECKER_H_ |
77 | |