/*
 * 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 "class_linker.h"
#include "compilation_unit.h"
#include "compiled_method.h"
#include "compiler.h"
#include "dex_cache.h"
#include "elf_image.h"
#include "elf_loader.h"
#include "ir_builder.h"
#include "jni_compiler.h"
#include "method_compiler.h"
#include "oat_compilation_unit.h"
#include "oat_file.h"
#include "stl_util.h"
#include "upcall_compiler.h"

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

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::compiler_llvm::InitialBackendOptions();

  // Initialize LLVM target, MC subsystem, asm printer, and asm parser
  llvm::InitializeAllTargets();
  llvm::InitializeAllTargetMCs();
  llvm::InitializeAllAsmPrinters();
  llvm::InitializeAllAsmParsers();
  // TODO: Maybe we don't have to initialize "all" targets.

  // 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 compiler_llvm {


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


CompilerLLVM::CompilerLLVM(Compiler* compiler, InstructionSet insn_set)
    : compiler_(compiler), compiler_lock_("llvm_compiler_lock"),
      insn_set_(insn_set), curr_cunit_(NULL) {


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


CompilerLLVM::~CompilerLLVM() {
  STLDeleteElements(&cunits_);
}


void CompilerLLVM::EnsureCompilationUnit() {
  compiler_lock_.AssertHeld();

  if (curr_cunit_ != NULL) {
    return;
  }

  // Allocate compilation unit
  size_t cunit_idx = cunits_.size();
  curr_cunit_ = new CompilationUnit(insn_set_, cunit_idx);

  // Register compilation unit
  cunits_.push_back(curr_cunit_);
}


void CompilerLLVM::MaterializeRemainder() {
  compiler_lock_.Lock();
  // Localize
  CompilationUnit* cunit = curr_cunit_;
  // Reset the curr_cuit_
  curr_cunit_ = NULL;
  compiler_lock_.Unlock();

  if (cunit != NULL) {
    Materialize(cunit);
  }
}


void CompilerLLVM::MaterializeIfThresholdReached() {
  compiler_lock_.Lock();
  // Localize
  CompilationUnit* cunit = curr_cunit_;

  if (curr_cunit_ != NULL && curr_cunit_->IsMaterializeThresholdReached()) {
    // Delete the compilation unit
    curr_cunit_ = NULL;
  } else {
    // Reset cunit such that Materialize() won't be invoked
    cunit = NULL;
  }

  compiler_lock_.Unlock();

  if (cunit != NULL) {
    Materialize(cunit);
  }
}


void CompilerLLVM::Materialize(CompilationUnit* cunit) {
  DCHECK(cunit != NULL);
  DCHECK(!cunit->IsMaterialized());

  // Write bitcode to file when filename is set
  if (IsBitcodeFileNameAvailable()) {
    const size_t cunit_idx = cunits_.size();
    cunit->SetBitcodeFileName(
      StringPrintf("%s-%zu", bitcode_filename_.c_str(), cunit_idx));
  }

  // Materialize the llvm::Module into ELF object file
  cunit->Materialize(compiler_->GetThreadCount());

  // Load ELF image when automatic ELF loading is enabled
  if (IsAutoElfLoadingEnabled()) {
    LoadElfFromCompilationUnit(cunit);
  }
}


void CompilerLLVM::EnableAutoElfLoading() {
  MutexLock GUARD(compiler_lock_);

  if (IsAutoElfLoadingEnabled()) {
    // If there is an existing ELF loader, then do nothing.
    // Because the existing ELF loader may have returned some code address
    // already.  If we replace the existing ELF loader with
    // elf_loader_.reset(...), then it is possible to have some dangling
    // pointer.
    return;
  }

  // Create ELF loader and load the materialized CompilationUnit
  elf_loader_.reset(new ElfLoader());

  for (size_t i = 0; i < cunits_.size(); ++i) {
    if (cunits_[i]->IsMaterialized()) {
      LoadElfFromCompilationUnit(cunits_[i]);
    }
  }
}


void CompilerLLVM::LoadElfFromCompilationUnit(const CompilationUnit* cunit) {
  MutexLock GUARD(compiler_lock_);
  DCHECK(cunit->IsMaterialized()) << cunit->GetElfIndex();

  if (!elf_loader_->LoadElfAt(cunit->GetElfIndex(),
                              cunit->GetElfImage(),
                              OatFile::kRelocAll)) {
    LOG(ERROR) << "Failed to load ELF from compilation unit "
               << cunit->GetElfIndex();
  }
}


const void* CompilerLLVM::GetMethodCodeAddr(const CompiledMethod* cm) const {
  return elf_loader_->GetMethodCodeAddr(cm->GetElfIndex(),
                                        cm->GetElfFuncIndex());
}


const Method::InvokeStub* CompilerLLVM::
GetMethodInvokeStubAddr(const CompiledInvokeStub* cm) const {
  return elf_loader_->GetMethodInvokeStubAddr(cm->GetElfIndex(),
                                              cm->GetElfFuncIndex());
}


std::vector<ElfImage> CompilerLLVM::GetElfImages() const {
  std::vector<ElfImage> result;

  for (size_t i = 0; i < cunits_.size(); ++i) {
    result.push_back(cunits_[i]->GetElfImage());
  }

  return result;
}


CompiledMethod* CompilerLLVM::
CompileDexMethod(OatCompilationUnit* oat_compilation_unit) {
  MutexLock GUARD(compiler_lock_);

  EnsureCompilationUnit();

  MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_);

  UniquePtr<MethodCompiler> method_compiler(
      new MethodCompiler(curr_cunit_, compiler_, oat_compilation_unit));

  return method_compiler->Compile();
}


CompiledMethod* CompilerLLVM::
CompileNativeMethod(OatCompilationUnit* oat_compilation_unit) {
  MutexLock GUARD(compiler_lock_);

  EnsureCompilationUnit();

  MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_);

  UniquePtr<JniCompiler> jni_compiler(
      new JniCompiler(curr_cunit_, *compiler_, oat_compilation_unit));

  return jni_compiler->Compile();
}


CompiledInvokeStub* CompilerLLVM::CreateInvokeStub(bool is_static,
                                                   char const *shorty) {
  MutexLock GUARD(compiler_lock_);

  EnsureCompilationUnit();

  MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_);

  UniquePtr<UpcallCompiler> upcall_compiler(
    new UpcallCompiler(curr_cunit_, *compiler_));

  return upcall_compiler->CreateStub(is_static, shorty);
}

} // namespace compiler_llvm
} // namespace art

inline static art::compiler_llvm::CompilerLLVM* ContextOf(art::Compiler& compiler) {
  void *compiler_context = compiler.GetCompilerContext();
  CHECK(compiler_context != NULL);
  return reinterpret_cast<art::compiler_llvm::CompilerLLVM*>(compiler_context);
}

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

extern "C" void ArtInitCompilerContext(art::Compiler& compiler) {
  CHECK(compiler.GetCompilerContext() == NULL);

  art::compiler_llvm::CompilerLLVM* compiler_llvm =
      new art::compiler_llvm::CompilerLLVM(&compiler,
                                           compiler.GetInstructionSet());

  compiler.SetCompilerContext(compiler_llvm);
}

extern "C" art::CompiledMethod* ArtCompileMethod(art::Compiler& compiler,
                                                 const art::DexFile::CodeItem* code_item,
                                                 uint32_t access_flags, uint32_t method_idx,
                                                 const art::ClassLoader* class_loader,
                                                 const art::DexFile& dex_file)
{
  art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
  art::DexCache *dex_cache = class_linker->FindDexCache(dex_file);

  art::OatCompilationUnit oat_compilation_unit(
    class_loader, class_linker, dex_file, *dex_cache, code_item,
    method_idx, access_flags);
  art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler);
  art::CompiledMethod* result = compiler_llvm->CompileDexMethod(&oat_compilation_unit);
  compiler_llvm->MaterializeIfThresholdReached();
  return result;
}

extern "C" art::CompiledMethod* ArtJniCompileMethod(art::Compiler& compiler,
                                                    uint32_t access_flags, uint32_t method_idx,
                                                    const art::DexFile& dex_file) {
  art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
  art::DexCache *dex_cache = class_linker->FindDexCache(dex_file);

  art::OatCompilationUnit oat_compilation_unit(
    NULL, class_linker, dex_file, *dex_cache, NULL,
    method_idx, access_flags);

  art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler);
  art::CompiledMethod* result = compiler_llvm->CompileNativeMethod(&oat_compilation_unit);
  compiler_llvm->MaterializeIfThresholdReached();
  return result;
}

extern "C" art::CompiledInvokeStub* ArtCreateInvokeStub(art::Compiler& compiler, bool is_static,
                                                        const char* shorty, uint32_t shorty_len) {
  art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler);
  art::CompiledInvokeStub* result = compiler_llvm->CreateInvokeStub(is_static, shorty);
  compiler_llvm->MaterializeIfThresholdReached();
  return result;
}

extern "C" void compilerLLVMSetBitcodeFileName(art::Compiler& compiler,
                                               std::string const& filename) {
  ContextOf(compiler)->SetBitcodeFileName(filename);
}

extern "C" void compilerLLVMMaterializeRemainder(art::Compiler& compiler) {
  ContextOf(compiler)->MaterializeRemainder();
}

extern "C" void compilerLLVMEnableAutoElfLoading(art::Compiler& compiler) {
  art::compiler_llvm::CompilerLLVM* compiler_llvm =
      reinterpret_cast<art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
  return compiler_llvm->EnableAutoElfLoading();
}

extern "C" const void* compilerLLVMGetMethodCodeAddr(const art::Compiler& compiler,
                                                     const art::CompiledMethod* cm,
                                                     const art::Method*) {
  const art::compiler_llvm::CompilerLLVM* compiler_llvm =
      reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
  return compiler_llvm->GetMethodCodeAddr(cm);
}

extern "C" const art::Method::InvokeStub* compilerLLVMGetMethodInvokeStubAddr(const art::Compiler& compiler,
                                                                              const art::CompiledInvokeStub* cm,
                                                                              const art::Method*) {
  const art::compiler_llvm::CompilerLLVM* compiler_llvm =
      reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
  return compiler_llvm->GetMethodInvokeStubAddr(cm);
}

extern "C" std::vector<art::ElfImage> compilerLLVMGetElfImages(const art::Compiler& compiler) {
  return ContextOf(compiler)->GetElfImages();
}

extern "C" void compilerLLVMDispose(art::Compiler& compiler) {
  delete ContextOf(compiler);
}
