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

// TODO: TargetLibraryInfo is included before sys/... because on Android bionic does #define tricks like:
//
// #define  stat64    stat
// #define  fstat64   fstat
// #define  lstat64   lstat
//
// which causes grief. bionic probably should not do that.
#include <llvm/Target/TargetLibraryInfo.h>

#include "llvm_compilation_unit.h"

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <string>

#include <llvm/ADT/OwningPtr.h>
#include <llvm/ADT/StringSet.h>
#include <llvm/ADT/Triple.h>
#include <llvm/Analysis/CallGraph.h>
#include <llvm/Analysis/CallGraphSCCPass.h>
#include <llvm/Analysis/Dominators.h>
#include <llvm/Analysis/LoopInfo.h>
#include <llvm/Analysis/LoopPass.h>
#include <llvm/Analysis/RegionPass.h>
#include <llvm/Analysis/ScalarEvolution.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Assembly/PrintModulePass.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/CodeGen/MachineFrameInfo.h>
#include <llvm/CodeGen/MachineFunction.h>
#include <llvm/CodeGen/MachineFunctionPass.h>
#include <llvm/DebugInfo.h>
#include <llvm/IR/DataLayout.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/Object/ObjectFile.h>
#include <llvm/PassManager.h>
#include <llvm/Support/Debug.h>
#include <llvm/Support/ELF.h>
#include <llvm/Support/FormattedStream.h>
#include <llvm/Support/ManagedStatic.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Support/PassNameParser.h>
#include <llvm/Support/PluginLoader.h>
#include <llvm/Support/PrettyStackTrace.h>
#include <llvm/Support/Signals.h>
#include <llvm/Support/SystemUtils.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/ToolOutputFile.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Support/system_error.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
#include <llvm/Transforms/Scalar.h>

#include "base/logging.h"
#include "base/unix_file/fd_file.h"
#include "compiled_method.h"
#include "compiler_llvm.h"
#include "instruction_set.h"
#include "ir_builder.h"
#include "os.h"
#include "runtime_support_builder_arm.h"
#include "runtime_support_builder_thumb2.h"
#include "runtime_support_builder_x86.h"
#include "utils_llvm.h"

namespace art {
namespace llvm {

::llvm::FunctionPass*
CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
                      CompilerDriver* compiler, const DexCompilationUnit* dex_compilation_unit);

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


LlvmCompilationUnit::LlvmCompilationUnit(const CompilerLLVM* compiler_llvm, size_t cunit_id)
    : compiler_llvm_(compiler_llvm), cunit_id_(cunit_id) {
  driver_ = NULL;
  dex_compilation_unit_ = NULL;
  llvm_info_.reset(new LLVMInfo());
  context_.reset(llvm_info_->GetLLVMContext());
  module_ = llvm_info_->GetLLVMModule();

  // Include the runtime function declaration
  makeLLVMModuleContents(module_);


  intrinsic_helper_.reset(new IntrinsicHelper(*context_, *module_));

  // Create IRBuilder
  irb_.reset(new IRBuilder(*context_, *module_, *intrinsic_helper_));

  // We always need a switch case, so just use a normal function.
  switch (GetInstructionSet()) {
  default:
    runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_));
    break;
  case kArm:
    runtime_support_.reset(new RuntimeSupportBuilderARM(*context_, *module_, *irb_));
    break;
  case kThumb2:
    runtime_support_.reset(new RuntimeSupportBuilderThumb2(*context_, *module_, *irb_));
    break;
  case kX86:
    runtime_support_.reset(new RuntimeSupportBuilderX86(*context_, *module_, *irb_));
    break;
  }

  irb_->SetRuntimeSupport(runtime_support_.get());
}


LlvmCompilationUnit::~LlvmCompilationUnit() {
  ::llvm::LLVMContext* llvm_context = context_.release(); // Managed by llvm_info_
  CHECK(llvm_context != NULL);
}


InstructionSet LlvmCompilationUnit::GetInstructionSet() const {
  return compiler_llvm_->GetInstructionSet();
}


static std::string DumpDirectory() {
  if (kIsTargetBuild) {
    return GetDalvikCacheOrDie(GetAndroidData());
  }
  return "/tmp";
}

void LlvmCompilationUnit::DumpBitcodeToFile() {
  std::string bitcode;
  DumpBitcodeToString(bitcode);
  std::string filename(StringPrintf("%s/Art%u.bc", DumpDirectory().c_str(), cunit_id_));
  UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
  output->WriteFully(bitcode.data(), bitcode.size());
  LOG(INFO) << ".bc file written successfully: " << filename;
}

void LlvmCompilationUnit::DumpBitcodeToString(std::string& str_buffer) {
  ::llvm::raw_string_ostream str_os(str_buffer);
  ::llvm::WriteBitcodeToFile(module_, str_os);
}

bool LlvmCompilationUnit::Materialize() {
  const bool kDumpBitcode = false;
  if (kDumpBitcode) {
    // Dump the bitcode for debugging
    DumpBitcodeToFile();
  }

  // Compile and prelink ::llvm::Module
  if (!MaterializeToString(elf_object_)) {
    LOG(ERROR) << "Failed to materialize compilation unit " << cunit_id_;
    return false;
  }

  const bool kDumpELF = false;
  if (kDumpELF) {
    // Dump the ELF image for debugging
    std::string filename(StringPrintf("%s/Art%u.o", DumpDirectory().c_str(), cunit_id_));
    UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
    output->WriteFully(elf_object_.data(), elf_object_.size());
    LOG(INFO) << ".o file written successfully: " << filename;
  }

  return true;
}


bool LlvmCompilationUnit::MaterializeToString(std::string& str_buffer) {
  ::llvm::raw_string_ostream str_os(str_buffer);
  return MaterializeToRawOStream(str_os);
}


bool LlvmCompilationUnit::MaterializeToRawOStream(::llvm::raw_ostream& out_stream) {
  // Lookup the LLVM target
  std::string target_triple;
  std::string target_cpu;
  std::string target_attr;
  CompilerDriver::InstructionSetToLLVMTarget(GetInstructionSet(), target_triple, target_cpu, target_attr);

  std::string errmsg;
  const ::llvm::Target* target =
    ::llvm::TargetRegistry::lookupTarget(target_triple, errmsg);

  CHECK(target != NULL) << errmsg;

  // Target options
  ::llvm::TargetOptions target_options;
  target_options.FloatABIType = ::llvm::FloatABI::Soft;
  target_options.NoFramePointerElim = true;
  target_options.NoFramePointerElimNonLeaf = true;
  target_options.UseSoftFloat = false;
  target_options.EnableFastISel = false;

  // Create the ::llvm::TargetMachine
  ::llvm::OwningPtr< ::llvm::TargetMachine> target_machine(
    target->createTargetMachine(target_triple, target_cpu, target_attr, target_options,
                                ::llvm::Reloc::Static, ::llvm::CodeModel::Small,
                                ::llvm::CodeGenOpt::Aggressive));

  CHECK(target_machine.get() != NULL) << "Failed to create target machine";

  // Add target data
  const ::llvm::DataLayout* data_layout = target_machine->getDataLayout();

  // PassManager for code generation passes
  ::llvm::PassManager pm;
  pm.add(new ::llvm::DataLayout(*data_layout));

  // FunctionPassManager for optimization pass
  ::llvm::FunctionPassManager fpm(module_);
  fpm.add(new ::llvm::DataLayout(*data_layout));

  if (bitcode_filename_.empty()) {
    // If we don't need write the bitcode to file, add the AddSuspendCheckToLoopLatchPass to the
    // regular FunctionPass.
    fpm.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
                                  driver_, dex_compilation_unit_));
  } else {
    ::llvm::FunctionPassManager fpm2(module_);
    fpm2.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
                                   driver_, dex_compilation_unit_));
    fpm2.doInitialization();
    for (::llvm::Module::iterator F = module_->begin(), E = module_->end();
         F != E; ++F) {
      fpm2.run(*F);
    }
    fpm2.doFinalization();

    // Write bitcode to file
    std::string errmsg;

    ::llvm::OwningPtr< ::llvm::tool_output_file> out_file(
      new ::llvm::tool_output_file(bitcode_filename_.c_str(), errmsg,
                                 ::llvm::raw_fd_ostream::F_Binary));


    if (!errmsg.empty()) {
      LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
      return false;
    }

    ::llvm::WriteBitcodeToFile(module_, out_file->os());
    out_file->keep();
  }

  // Add optimization pass
  ::llvm::PassManagerBuilder pm_builder;
  // TODO: Use inliner after we can do IPO.
  pm_builder.Inliner = NULL;
  //pm_builder.Inliner = ::llvm::createFunctionInliningPass();
  //pm_builder.Inliner = ::llvm::createAlwaysInlinerPass();
  //pm_builder.Inliner = ::llvm::createPartialInliningPass();
  pm_builder.OptLevel = 3;
  pm_builder.DisableSimplifyLibCalls = 1;
  pm_builder.DisableUnitAtATime = 1;
  pm_builder.populateFunctionPassManager(fpm);
  pm_builder.populateModulePassManager(pm);
  pm.add(::llvm::createStripDeadPrototypesPass());

  // Add passes to emit ELF image
  {
    ::llvm::formatted_raw_ostream formatted_os(out_stream, false);

    // Ask the target to add backend passes as necessary.
    if (target_machine->addPassesToEmitFile(pm,
                                            formatted_os,
                                            ::llvm::TargetMachine::CGFT_ObjectFile,
                                            true)) {
      LOG(FATAL) << "Unable to generate ELF for this target";
      return false;
    }

    // Run the per-function optimization
    fpm.doInitialization();
    for (::llvm::Module::iterator F = module_->begin(), E = module_->end();
         F != E; ++F) {
      fpm.run(*F);
    }
    fpm.doFinalization();

    // Run the code generation passes
    pm.run(*module_);
  }

  return true;
}

// Check whether the align is less than or equal to the code alignment of
// that architecture.  Since the Oat writer only guarantee that the compiled
// method being aligned to kArchAlignment, we have no way to align the ELf
// section if the section alignment is greater than kArchAlignment.
void LlvmCompilationUnit::CheckCodeAlign(uint32_t align) const {
  InstructionSet insn_set = GetInstructionSet();
  switch (insn_set) {
  case kThumb2:
  case kArm:
    CHECK_LE(align, static_cast<uint32_t>(kArmAlignment));
    break;

  case kX86:
    CHECK_LE(align, static_cast<uint32_t>(kX86Alignment));
    break;

  case kMips:
    CHECK_LE(align, static_cast<uint32_t>(kMipsAlignment));
    break;

  default:
    LOG(FATAL) << "Unknown instruction set: " << insn_set;
  }
}


} // namespace llvm
} // namespace art
