/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ART_COMPILER_OPTIMIZING_GRAPH_CHECKER_H_ #define ART_COMPILER_OPTIMIZING_GRAPH_CHECKER_H_ #include "nodes.h" #include <ostream> namespace art { // A control-flow graph visitor performing various checks. class GraphChecker : public HGraphDelegateVisitor { public: explicit GraphChecker(HGraph* graph, const char* dump_prefix = "art::GraphChecker: ") : HGraphDelegateVisitor(graph), errors_(graph->GetArena()->Adapter(kArenaAllocGraphChecker)), dump_prefix_(dump_prefix), seen_ids_(graph->GetArena(), graph->GetCurrentInstructionId(), false, kArenaAllocGraphChecker), blocks_storage_(graph->GetArena()->Adapter(kArenaAllocGraphChecker)), visited_storage_(graph->GetArena(), 0u, true, kArenaAllocGraphChecker) {} // Check the whole graph (in reverse post-order). void Run() { // VisitReversePostOrder is used instead of VisitInsertionOrder, // as the latter might visit dead blocks removed by the dominator // computation. VisitReversePostOrder(); } void VisitBasicBlock(HBasicBlock* block) OVERRIDE; void VisitInstruction(HInstruction* instruction) OVERRIDE; void VisitPhi(HPhi* phi) OVERRIDE; void VisitBinaryOperation(HBinaryOperation* op) OVERRIDE; void VisitBooleanNot(HBooleanNot* instruction) OVERRIDE; void VisitBoundType(HBoundType* instruction) OVERRIDE; void VisitBoundsCheck(HBoundsCheck* check) OVERRIDE; void VisitCheckCast(HCheckCast* check) OVERRIDE; void VisitCondition(HCondition* op) OVERRIDE; void VisitConstant(HConstant* instruction) OVERRIDE; void VisitDeoptimize(HDeoptimize* instruction) OVERRIDE; void VisitIf(HIf* instruction) OVERRIDE; void VisitInstanceOf(HInstanceOf* check) OVERRIDE; void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE; void VisitLoadException(HLoadException* load) OVERRIDE; void VisitNeg(HNeg* instruction) OVERRIDE; void VisitPackedSwitch(HPackedSwitch* instruction) OVERRIDE; void VisitReturn(HReturn* ret) OVERRIDE; void VisitReturnVoid(HReturnVoid* ret) OVERRIDE; void VisitSelect(HSelect* instruction) OVERRIDE; void VisitTryBoundary(HTryBoundary* try_boundary) OVERRIDE; void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE; void HandleLoop(HBasicBlock* loop_header); void HandleBooleanInput(HInstruction* instruction, size_t input_index); // Was the last visit of the graph valid? bool IsValid() const { return errors_.empty(); } // Get the list of detected errors. const ArenaVector<std::string>& GetErrors() const { return errors_; } // Print detected errors on output stream `os`. void Dump(std::ostream& os) const { for (size_t i = 0, e = errors_.size(); i < e; ++i) { os << dump_prefix_ << errors_[i] << std::endl; } } protected: // Report a new error. void AddError(const std::string& error) { errors_.push_back(error); } // The block currently visited. HBasicBlock* current_block_ = nullptr; // Errors encountered while checking the graph. ArenaVector<std::string> errors_; private: // String displayed before dumped errors. const char* const dump_prefix_; ArenaBitVector seen_ids_; // To reduce the total arena memory allocation, we reuse the same storage. ArenaVector<HBasicBlock*> blocks_storage_; ArenaBitVector visited_storage_; DISALLOW_COPY_AND_ASSIGN(GraphChecker); }; } // namespace art #endif // ART_COMPILER_OPTIMIZING_GRAPH_CHECKER_H_