/*
 * 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.
 */

#include <dlfcn.h>

#include "base/logging.h"
#include "base/macros.h"
#include "bb_optimizations.h"
#include "compiler_internals.h"
#include "dataflow_iterator.h"
#include "dataflow_iterator-inl.h"
#include "pass.h"
#include "pass_driver.h"

namespace art {

namespace {  // anonymous namespace

/**
 * @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;
}

void DoWalkBasicBlocks(CompilationUnit* c_unit, const Pass* pass, DataflowIterator* iterator) {
  // Paranoid: Check the iterator before walking the BasicBlocks.
  DCHECK(iterator != nullptr);

  bool change = false;
  for (BasicBlock *bb = iterator->Next(change); bb != 0; bb = iterator->Next(change)) {
    change = pass->WalkBasicBlocks(c_unit, bb);
  }
}

template <typename Iterator>
inline void DoWalkBasicBlocks(CompilationUnit* c_unit, const Pass* pass) {
  Iterator iterator(c_unit->mir_graph.get());
  DoWalkBasicBlocks(c_unit, pass, &iterator);
}

}  // anonymous namespace

PassDriver::PassDriver(CompilationUnit* cu, bool create_default_passes)
    : cu_(cu), dump_cfg_folder_("/sdcard/") {
  DCHECK(cu != nullptr);

  // If need be, create the default passes.
  if (create_default_passes) {
    CreatePasses();
  }
}

PassDriver::~PassDriver() {
}

void PassDriver::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);
}

void PassDriver::CreatePasses() {
  /*
   * Create the pass list. These passes are immutable and are shared across the threads.
   *
   * Advantage is that there will be no race conditions here.
   * Disadvantage is the passes can't change their internal states depending on CompilationUnit:
   *   - This is not yet an issue: no current pass would require it.
   */
  static const Pass* const passes[] = {
      GetPassInstance<CodeLayout>(),
      GetPassInstance<SSATransformation>(),
      GetPassInstance<ConstantPropagation>(),
      GetPassInstance<InitRegLocations>(),
      GetPassInstance<MethodUseCount>(),
      GetPassInstance<NullCheckEliminationAndTypeInferenceInit>(),
      GetPassInstance<NullCheckEliminationAndTypeInference>(),
      GetPassInstance<BBCombine>(),
      GetPassInstance<BBOptimizations>(),
  };

  // Insert each pass into the list via the InsertPass method.
  pass_list_.reserve(arraysize(passes));
  for (const Pass* pass : passes) {
    InsertPass(pass);
  }
}

void PassDriver::HandlePassFlag(CompilationUnit* c_unit, const Pass* pass) {
  // Unused parameters for the moment.
  UNUSED(c_unit);
  UNUSED(pass);
}

void PassDriver::DispatchPass(CompilationUnit* c_unit, const Pass* curPass) {
  LOG(DEBUG) << "Dispatching " << curPass->GetName();

  DataFlowAnalysisMode mode = curPass->GetTraversal();

  switch (mode) {
    case kPreOrderDFSTraversal:
      DoWalkBasicBlocks<PreOrderDfsIterator>(c_unit, curPass);
      break;
    case kRepeatingPreOrderDFSTraversal:
      DoWalkBasicBlocks<RepeatingPreOrderDfsIterator>(c_unit, curPass);
      break;
    case kRepeatingPostOrderDFSTraversal:
      DoWalkBasicBlocks<RepeatingPostOrderDfsIterator>(c_unit, curPass);
      break;
    case kReversePostOrderDFSTraversal:
      DoWalkBasicBlocks<ReversePostOrderDfsIterator>(c_unit, curPass);
      break;
    case kRepeatingReversePostOrderDFSTraversal:
      DoWalkBasicBlocks<RepeatingReversePostOrderDfsIterator>(c_unit, curPass);
      break;
    case kPostOrderDOMTraversal:
      DoWalkBasicBlocks<PostOrderDOMIterator>(c_unit, curPass);
      break;
    case kAllNodes:
      DoWalkBasicBlocks<AllNodesIterator>(c_unit, curPass);
      break;
    case kNoNodes:
      break;
    default:
      LOG(DEBUG) << "Iterator mode not handled in dispatcher: " << mode;
      break;
  }
}

void PassDriver::ApplyPass(CompilationUnit* c_unit, const Pass* curPass) {
  curPass->Start(c_unit);
  DispatchPass(c_unit, curPass);
  curPass->End(c_unit);
}

bool PassDriver::RunPass(CompilationUnit* c_unit, const Pass* pass, bool time_split) {
  // Paranoid: c_unit and pass cannot be nullptr, and the pass should have a name.
  DCHECK(c_unit != nullptr);
  DCHECK(pass != nullptr);
  DCHECK(pass->GetName() != nullptr && pass->GetName()[0] != 0);

  // Do we perform a time split
  if (time_split) {
    c_unit->NewTimingSplit(pass->GetName());
  }

  // Check the pass gate first.
  bool should_apply_pass = pass->Gate(c_unit);

  if (should_apply_pass) {
    // Applying the pass: first start, doWork, and end calls.
    ApplyPass(c_unit, pass);

    // Clean up if need be.
    HandlePassFlag(c_unit, pass);

    // Do we want to log it?
    if ((c_unit->enable_debug&  (1 << kDebugDumpCFG)) != 0) {
      // Do we have a pass folder?
      const char* passFolder = pass->GetDumpCFGFolder();
      DCHECK(passFolder != nullptr);

      if (passFolder[0] != 0) {
        // Create directory prefix.
        std::string prefix = GetDumpCFGFolder();
        prefix += passFolder;
        prefix += "/";

        c_unit->mir_graph->DumpCFG(prefix.c_str(), false);
      }
    }
  }

  // If the pass gate passed, we can declare success.
  return should_apply_pass;
}

bool PassDriver::RunPass(CompilationUnit* c_unit, const char* pass_name) {
  // Paranoid: c_unit cannot be nullptr and we need a pass name.
  DCHECK(c_unit != nullptr);
  DCHECK(pass_name != nullptr && pass_name[0] != 0);

  const Pass* cur_pass = GetPass(pass_name);

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

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

void PassDriver::Launch() {
  for (const Pass* cur_pass : pass_list_) {
    RunPass(cu_, cur_pass, true);
  }
}

void PassDriver::PrintPassNames() const {
  LOG(INFO) << "Loop Passes are:";

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

const Pass* PassDriver::GetPass(const char* name) const {
  for (const Pass* cur_pass : pass_list_) {
    if (strcmp(name, cur_pass->GetName()) == 0) {
      return cur_pass;
    }
  }
  return nullptr;
}

}  // namespace art
