/*
 * 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_DEX_PASS_DRIVER_H_
#define ART_COMPILER_DEX_PASS_DRIVER_H_

#include <vector>
#include "pass.h"
#include "safe_map.h"

// Forward Declarations.
class Pass;
class PassDriver;
namespace art {
/**
 * @brief Helper function to create a single instance of a given Pass and can be shared across
 * the threads.
 */
template <typename PassType>
const Pass* GetPassInstance() {
  static const PassType pass;
  return &pass;
}

// Empty holder for the constructor.
class PassDriverDataHolder {
};

/**
 * @class PassDriver
 * @brief PassDriver is the wrapper around all Pass instances in order to execute them
 */
template <typename PassDriverType>
class PassDriver {
 public:
  explicit PassDriver() {
    InitializePasses();
  }

  virtual ~PassDriver() {
  }

  /**
   * @brief Insert a Pass: can warn if multiple passes have the same name.
   */
  void InsertPass(const Pass* new_pass) {
    DCHECK(new_pass != nullptr);
    DCHECK(new_pass->GetName() != nullptr && new_pass->GetName()[0] != 0);

    // It is an error to override an existing pass.
    DCHECK(GetPass(new_pass->GetName()) == nullptr)
        << "Pass name " << new_pass->GetName() << " already used.";

    // Now add to the list.
    pass_list_.push_back(new_pass);
  }

  /**
   * @brief Run a pass using the name as key.
   * @return whether the pass was applied.
   */
  virtual bool RunPass(const char* pass_name) {
    // Paranoid: c_unit cannot be nullptr and we need a pass name.
    DCHECK(pass_name != nullptr && pass_name[0] != 0);

    const Pass* cur_pass = GetPass(pass_name);

    if (cur_pass != nullptr) {
      return RunPass(cur_pass);
    }

    // Return false, we did not find the pass.
    return false;
  }

  /**
   * @brief Runs all the passes with the pass_list_.
   */
  void Launch() {
    for (const Pass* cur_pass : pass_list_) {
      RunPass(cur_pass);
    }
  }

  /**
   * @brief Searches for a particular pass.
   * @param the name of the pass to be searched for.
   */
  const Pass* GetPass(const char* name) const {
    for (const Pass* cur_pass : pass_list_) {
      if (strcmp(name, cur_pass->GetName()) == 0) {
        return cur_pass;
      }
    }
    return nullptr;
  }

  static void CreateDefaultPassList(const std::string& disable_passes) {
    // Insert each pass from g_passes into g_default_pass_list.
    PassDriverType::g_default_pass_list.clear();
    PassDriverType::g_default_pass_list.reserve(PassDriver<PassDriverType>::g_passes_size);
    for (uint16_t i = 0; i < PassDriver<PassDriverType>::g_passes_size; ++i) {
      const Pass* pass = PassDriver<PassDriverType>::g_passes[i];
      // Check if we should disable this pass.
      if (disable_passes.find(pass->GetName()) != std::string::npos) {
        LOG(INFO) << "Skipping " << pass->GetName();
      } else {
        PassDriver<PassDriverType>::g_default_pass_list.push_back(pass);
      }
    }
  }

  /**
   * @brief Run a pass using the Pass itself.
   * @param time_split do we want a time split request(default: false)?
   * @return whether the pass was applied.
   */
  virtual bool RunPass(const Pass* pass, bool time_split = false) = 0;

  /**
   * @brief Print the pass names of all the passes available.
   */
  static void PrintPassNames() {
    LOG(INFO) << "Loop Passes are:";

    for (const Pass* cur_pass : PassDriver<PassDriverType>::g_default_pass_list) {
      LOG(INFO) << "\t-" << cur_pass->GetName();
    }
  }

  /**
   * @brief Gets the list of passes currently schedule to execute.
   * @return pass_list_
   */
  std::vector<const Pass*>& GetPasses() {
    return pass_list_;
  }

  static void SetPrintAllPasses() {
    default_print_passes_ = true;
  }

  static void SetDumpPassList(const std::string& list) {
    dump_pass_list_ = list;
  }

  static void SetPrintPassList(const std::string& list) {
    print_pass_list_ = list;
  }

  void SetDefaultPasses() {
    pass_list_ = PassDriver<PassDriverType>::g_default_pass_list;
  }

 protected:
  virtual void InitializePasses() {
    SetDefaultPasses();
  }

  /**
   * @brief Apply a patch: perform start/work/end functions.
   */
  virtual void ApplyPass(PassDataHolder* data, const Pass* pass) {
    pass->Start(data);
    DispatchPass(pass);
    pass->End(data);
  }
  /**
   * @brief Dispatch a patch.
   * Gives the ability to add logic when running the patch.
   */
  virtual void DispatchPass(const Pass* pass) {
    UNUSED(pass);
  }

  /** @brief List of passes: provides the order to execute the passes. */
  std::vector<const Pass*> pass_list_;

  /** @brief The number of passes within g_passes.  */
  static const uint16_t g_passes_size;

  /** @brief The number of passes within g_passes.  */
  static const Pass* const g_passes[];

  /** @brief The default pass list is used to initialize pass_list_. */
  static std::vector<const Pass*> g_default_pass_list;

  /** @brief Do we, by default, want to be printing the log messages? */
  static bool default_print_passes_;

  /** @brief What are the passes we want to be printing the log messages? */
  static std::string print_pass_list_;

  /** @brief What are the passes we want to be dumping the CFG? */
  static std::string dump_pass_list_;
};

}  // namespace art
#endif  // ART_COMPILER_DEX_PASS_DRIVER_H_
