/*
 * 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) {}

  // 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 VisitIf(HIf* instruction) OVERRIDE;
  void VisitInstanceOf(HInstanceOf* check) OVERRIDE;
  void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE;
  void VisitLoadException(HLoadException* load) 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 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_;

  DISALLOW_COPY_AND_ASSIGN(GraphChecker);
};

}  // namespace art

#endif  // ART_COMPILER_OPTIMIZING_GRAPH_CHECKER_H_
