| 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 | |