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