/*
 * Copyright (C) 2012 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 "compiler_llvm.h"

#include "backend_options.h"
#include "base/stl_util.h"
#include "class_linker.h"
#include "compiled_method.h"
#include "dex/verification_results.h"
#include "dex/verified_method.h"
#include "driver/compiler_driver.h"
#include "driver/dex_compilation_unit.h"
#include "globals.h"
#include "ir_builder.h"
#include "jni/portable/jni_compiler.h"
#include "llvm_compilation_unit.h"
#include "thread-inl.h"
#include "utils_llvm.h"
#include "verifier/method_verifier.h"

#include <llvm/LinkAllPasses.h>
#include <llvm/Support/ManagedStatic.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/Threading.h>

namespace art {
void CompileOneMethod(CompilerDriver& driver,
                      Compiler* compiler,
                      const DexFile::CodeItem* code_item,
                      uint32_t access_flags, InvokeType invoke_type,
                      uint16_t class_def_idx, uint32_t method_idx, jobject class_loader,
                      const DexFile& dex_file,
                      void* llvm_info);
}

namespace llvm {
  extern bool TimePassesIsEnabled;
}

namespace {

pthread_once_t llvm_initialized = PTHREAD_ONCE_INIT;

void InitializeLLVM() {
  // Initialize LLVM internal data structure for multithreading
  llvm::llvm_start_multithreaded();

  // NOTE: Uncomment following line to show the time consumption of LLVM passes
  // llvm::TimePassesIsEnabled = true;

  // Initialize LLVM target-specific options.
  art::llvm::InitialBackendOptions();

  // Initialize LLVM target, MC subsystem, asm printer, and asm parser.
  if (art::kIsTargetBuild) {
    // Don't initialize all targets on device. Just initialize the device's native target
    llvm::InitializeNativeTarget();
    llvm::InitializeNativeTargetAsmPrinter();
    llvm::InitializeNativeTargetAsmParser();
  } else {
    llvm::InitializeAllTargets();
    llvm::InitializeAllTargetMCs();
    llvm::InitializeAllAsmPrinters();
    llvm::InitializeAllAsmParsers();
  }

  // Initialize LLVM optimization passes
  llvm::PassRegistry &registry = *llvm::PassRegistry::getPassRegistry();

  llvm::initializeCore(registry);
  llvm::initializeScalarOpts(registry);
  llvm::initializeIPO(registry);
  llvm::initializeAnalysis(registry);
  llvm::initializeIPA(registry);
  llvm::initializeTransformUtils(registry);
  llvm::initializeInstCombine(registry);
  llvm::initializeInstrumentation(registry);
  llvm::initializeTarget(registry);
}

// The Guard to Shutdown LLVM
// llvm::llvm_shutdown_obj llvm_guard;
// TODO: We are commenting out this line because this will cause SEGV from
// time to time.
// Two reasons: (1) the order of the destruction of static objects, or
//              (2) dlopen/dlclose side-effect on static objects.

}  // anonymous namespace


namespace art {
namespace llvm {


::llvm::Module* makeLLVMModuleContents(::llvm::Module* module);


CompilerLLVM::CompilerLLVM(CompilerDriver* driver, InstructionSet insn_set)
    : compiler_driver_(driver), insn_set_(insn_set),
      next_cunit_id_lock_("compilation unit id lock"), next_cunit_id_(1) {

  // Initialize LLVM libraries
  pthread_once(&llvm_initialized, InitializeLLVM);
}


CompilerLLVM::~CompilerLLVM() {
}


LlvmCompilationUnit* CompilerLLVM::AllocateCompilationUnit() {
  MutexLock GUARD(Thread::Current(), next_cunit_id_lock_);
  LlvmCompilationUnit* cunit = new LlvmCompilationUnit(this, next_cunit_id_++);
  if (!bitcode_filename_.empty()) {
    cunit->SetBitcodeFileName(StringPrintf("%s-%u",
                                           bitcode_filename_.c_str(),
                                           cunit->GetCompilationUnitId()));
  }
  return cunit;
}


CompiledMethod* CompilerLLVM::
CompileDexMethod(DexCompilationUnit* dex_compilation_unit, InvokeType invoke_type) {
  std::unique_ptr<LlvmCompilationUnit> cunit(AllocateCompilationUnit());

  cunit->SetDexCompilationUnit(dex_compilation_unit);
  cunit->SetCompilerDriver(compiler_driver_);
  // TODO: consolidate ArtCompileMethods
  CompileOneMethod(compiler_driver_,
                   compiler_driver_->GetCompiler(),
                   dex_compilation_unit->GetCodeItem(),
                   dex_compilation_unit->GetAccessFlags(),
                   invoke_type,
                   dex_compilation_unit->GetClassDefIndex(),
                   dex_compilation_unit->GetDexMethodIndex(),
                   dex_compilation_unit->GetClassLoader(),
                   *dex_compilation_unit->GetDexFile(),
                   cunit.get());

  cunit->Materialize();

  return new CompiledMethod(*compiler_driver_, compiler_driver_->GetInstructionSet(),
                            cunit->GetElfObject(),
                            dex_compilation_unit->GetVerifiedMethod()->GetDexGcMap(),
                            cunit->GetDexCompilationUnit()->GetSymbol());
}


CompiledMethod* CompilerLLVM::
CompileNativeMethod(DexCompilationUnit* dex_compilation_unit) {
  std::unique_ptr<LlvmCompilationUnit> cunit(AllocateCompilationUnit());

  std::unique_ptr<JniCompiler> jni_compiler(
      new JniCompiler(cunit.get(), compiler_driver_, dex_compilation_unit));

  return jni_compiler->Compile();
}


static CompilerLLVM* ContextOf(art::CompilerDriver* driver) {
  void *compiler_context = driver->GetCompilerContext();
  CHECK(compiler_context != NULL);
  return reinterpret_cast<CompilerLLVM*>(compiler_context);
}

static CompilerLLVM* ContextOf(const art::CompilerDriver& driver) {
  void *compiler_context = driver.GetCompilerContext();
  CHECK(compiler_context != NULL);
  return reinterpret_cast<CompilerLLVM*>(compiler_context);
}

void ArtInitCompilerContext(CompilerDriver* driver) {
  CHECK(driver->GetCompilerContext() == nullptr);

  CompilerLLVM* compiler_llvm = new CompilerLLVM(driver, driver->GetInstructionSet());

  driver->SetCompilerContext(compiler_llvm);
}

void ArtUnInitCompilerContext(CompilerDriver* driver) {
  delete ContextOf(driver);
  driver->SetCompilerContext(nullptr);
}

CompiledMethod* ArtCompileMethod(CompilerDriver* driver, const DexFile::CodeItem* code_item,
                                 uint32_t access_flags, InvokeType invoke_type,
                                 uint16_t class_def_idx, uint32_t method_idx, jobject class_loader,
                                 const DexFile& dex_file) {
  UNUSED(class_def_idx);  // TODO: this is used with Compiler::RequiresConstructorBarrier.
  ClassLinker *class_linker = Runtime::Current()->GetClassLinker();

  DexCompilationUnit dex_compilation_unit(nullptr, class_loader, class_linker, dex_file, code_item,
                                          class_def_idx, method_idx, access_flags,
                                          driver->GetVerifiedMethod(&dex_file, method_idx));
  CompilerLLVM* compiler_llvm = ContextOf(driver);
  CompiledMethod* result = compiler_llvm->CompileDexMethod(&dex_compilation_unit, invoke_type);
  return result;
}

CompiledMethod* ArtLLVMJniCompileMethod(CompilerDriver* driver, uint32_t access_flags,
                                        uint32_t method_idx, const DexFile& dex_file) {
  ClassLinker *class_linker = Runtime::Current()->GetClassLinker();

  DexCompilationUnit dex_compilation_unit(nullptr, nullptr, class_linker, dex_file, nullptr,
                                          0, method_idx, access_flags, nullptr);

  CompilerLLVM* compiler_llvm = ContextOf(driver);
  CompiledMethod* result = compiler_llvm->CompileNativeMethod(&dex_compilation_unit);
  return result;
}

void compilerLLVMSetBitcodeFileName(const CompilerDriver& driver, const std::string& filename) {
  ContextOf(driver)->SetBitcodeFileName(filename);
}

}  // namespace llvm
}  // namespace art

