/*
 * 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 "llvm_compilation_unit.h"

#include "base/logging.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 <llvm/ADT/OwningPtr.h>
#include <llvm/ADT/StringSet.h>
#include <llvm/ADT/Triple.h>
#include <llvm/Analysis/CallGraph.h>
#include <llvm/Analysis/DebugInfo.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/CallGraphSCCPass.h>
#include <llvm/CodeGen/MachineFrameInfo.h>
#include <llvm/CodeGen/MachineFunction.h>
#include <llvm/CodeGen/MachineFunctionPass.h>
#include <llvm/DerivedTypes.h>
#include <llvm/LLVMContext.h>
#include <llvm/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/TargetData.h>
#include <llvm/Target/TargetLibraryInfo.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
#include <llvm/Transforms/Scalar.h>

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

#include <string>

namespace art {
namespace compiler_llvm {

#if defined(ART_USE_PORTABLE_COMPILER)
llvm::FunctionPass*
CreateGBCExpanderPass(const greenland::IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
                      Compiler* compiler, OatCompilationUnit* oat_compilation_unit);
#endif

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


LlvmCompilationUnit::LlvmCompilationUnit(const CompilerLLVM* compiler_llvm,
                                 size_t cunit_idx)
: compiler_llvm_(compiler_llvm), cunit_idx_(cunit_idx) {
#if !defined(ART_USE_PORTABLE_COMPILER)
  context_.reset(new llvm::LLVMContext());
  module_ = new llvm::Module("art", *context_);
#else
  compiler_ = NULL;
  oat_compilation_unit_ = NULL;
  llvm_info_.reset(new LLVMInfo());
  context_.reset(llvm_info_->GetLLVMContext());
  module_ = llvm_info_->GetLLVMModule();
#endif

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

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

  // 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() {
#if defined(ART_USE_PORTABLE_COMPILER)
  llvm::LLVMContext* llvm_context = context_.release(); // Managed by llvm_info_
  CHECK(llvm_context != NULL);
#endif
}


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


bool LlvmCompilationUnit::Materialize() {
  std::string elf_image;

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

#if 0
  // Dump the ELF image for debugging
  std::string filename(StringPrintf("%s/Art%zu.elf",
                                    GetArtCacheOrDie(GetAndroidData()).c_str(),
                                    cunit_idx_));
  UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
  output->WriteFully(elf_image.data(), elf_image.size());
#endif

  // Extract the .text section and prelink the code
  if (!ExtractCodeAndPrelink(elf_image)) {
    LOG(ERROR) << "Failed to extract code from compilation unit " << cunit_idx_;
    return false;
  }

  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;
  Compiler::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::TargetData* target_data = target_machine->getTargetData();

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

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

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

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

bool LlvmCompilationUnit::ExtractCodeAndPrelink(const std::string& elf_image) {
  if (GetInstructionSet() == kX86) {
    compiled_code_.push_back(0xccU);
    compiled_code_.push_back(0xccU);
    compiled_code_.push_back(0xccU);
    compiled_code_.push_back(0xccU);
    return true;
  }

  llvm::OwningPtr<llvm::MemoryBuffer> elf_image_buff(
    llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(elf_image.data(),
                                                     elf_image.size())));

  llvm::OwningPtr<llvm::object::ObjectFile> elf_file(
    llvm::object::ObjectFile::createELFObjectFile(elf_image_buff.take()));

  llvm::error_code ec;

  const ProcedureLinkageTable& plt = compiler_llvm_->GetProcedureLinkageTable();

  for (llvm::object::section_iterator
       sec_iter = elf_file->begin_sections(),
       sec_end = elf_file->end_sections();
       sec_iter != sec_end; sec_iter.increment(ec)) {

    CHECK(ec == 0) << "Failed to read section because " << ec.message();

    // Read the section information
    llvm::StringRef name;
    uint64_t alignment = 0u;
    uint64_t size = 0u;

    CHECK(sec_iter->getName(name) == 0);
    CHECK(sec_iter->getSize(size) == 0);
    CHECK(sec_iter->getAlignment(alignment) == 0);

    if (name == ".data" || name == ".bss" || name == ".rodata") {
      if (size > 0) {
        LOG(FATAL) << "Compilation unit " << cunit_idx_ << " has non-empty "
                   << name.str() << " section";
      }

    } else if (name == "" || name == ".rel.text" ||
               name == ".ARM.attributes" || name == ".symtab" ||
               name == ".strtab" || name == ".shstrtab") {
      // We can ignore these sections.  We don't have to copy them into
      // the result Oat file.

    } else if (name == ".text") {
      // Ensure the alignment requirement is less than or equal to
      // kArchAlignment
      CheckCodeAlign(alignment);

      // Copy the compiled code
      llvm::StringRef contents;
      CHECK(sec_iter->getContents(contents) == 0);

      copy(contents.data(),
           contents.data() + contents.size(),
           back_inserter(compiled_code_));

      // Prelink the compiled code
      for (llvm::object::relocation_iterator
           rel_iter = sec_iter->begin_relocations(),
           rel_end = sec_iter->end_relocations(); rel_iter != rel_end;
           rel_iter.increment(ec)) {

        CHECK(ec == 0) << "Failed to read relocation because " << ec.message();

        // Read the relocation information
        llvm::object::SymbolRef sym_ref;
        uint64_t rel_offset = 0;
        uint64_t rel_type = 0;
        int64_t rel_addend = 0;

        CHECK(rel_iter->getSymbol(sym_ref) == 0);
        CHECK(rel_iter->getOffset(rel_offset) == 0);
        CHECK(rel_iter->getType(rel_type) == 0);
        CHECK(rel_iter->getAdditionalInfo(rel_addend) == 0);

        // Read the symbol related to this relocation fixup
        llvm::StringRef sym_name;
        CHECK(sym_ref.getName(sym_name) == 0);

        // Relocate the fixup.
        // TODO: Support more relocation type.
        CHECK(rel_type == llvm::ELF::R_ARM_ABS32);
        CHECK_LE(rel_offset + 4, compiled_code_.size());

        uintptr_t dest_addr = plt.GetEntryAddress(sym_name.str().c_str());
        uintptr_t final_addr = dest_addr + rel_addend;
        compiled_code_[rel_offset] = final_addr & 0xff;
        compiled_code_[rel_offset + 1] = (final_addr >> 8) & 0xff;
        compiled_code_[rel_offset + 2] = (final_addr >> 16) & 0xff;
        compiled_code_[rel_offset + 3] = (final_addr >> 24) & 0xff;
      }

    } else {
      LOG(WARNING) << "Unexpected section: " << name.str();
    }
  }

  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 compiler_llvm
} // namespace art
