//===- SectLinker.cpp -----------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the SectLinker class.
//
//===----------------------------------------------------------------------===//
#include <mcld/Support/FileHandle.h>
#include <mcld/MC/InputTree.h>
#include <mcld/MC/MCLDDriver.h>
#include <mcld/Support/FileSystem.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Support/FileHandle.h>
#include <mcld/Support/raw_ostream.h>
#include <mcld/Support/MemoryAreaFactory.h>
#include <mcld/Support/DerivedPositionDependentOptions.h>
#include <mcld/Target/TargetLDBackend.h>
#include <mcld/CodeGen/SectLinker.h>
#include <mcld/CodeGen/SectLinkerOption.h>

#include <llvm/Module.h>

#include <algorithm>
#include <stack>
#include <string>

using namespace mcld;
using namespace llvm;

//===----------------------------------------------------------------------===//
// Forward declarations
char SectLinker::m_ID = 0;
static bool CompareOption(const PositionDependentOption* X,
                          const PositionDependentOption* Y);

//===----------------------------------------------------------------------===//
// SectLinker
SectLinker::SectLinker(SectLinkerOption &pOption,
                       TargetLDBackend& pLDBackend)
  : MachineFunctionPass(m_ID),
    m_pOption(&pOption),
    m_pLDBackend(&pLDBackend),
    m_pLDDriver(NULL),
    m_pMemAreaFactory(NULL)
{
  m_pMemAreaFactory = new MemoryAreaFactory(32);
}

SectLinker::~SectLinker()
{
  delete m_pLDDriver;

  // FIXME: current implementation can not change the order of delete.
  //
  // Instance of TargetLDBackend was created outside and is not managed by
  // SectLinker. It should not be destroyed here and by SectLinker. However, in
  // order to follow the LLVM convention - that is, the pass manages all the
  // objects it used during the processing, we destroy the object of
  // TargetLDBackend here.
  delete m_pLDBackend;

  delete m_pMemAreaFactory;
}

bool SectLinker::doInitialization(Module &pM)
{
  MCLDInfo &info = m_pOption->info();

  // ----- convert position dependent options into tree of input files  ----- //
  PositionDependentOptions &PosDepOpts = m_pOption->pos_dep_options();
  std::stable_sort(PosDepOpts.begin(), PosDepOpts.end(), CompareOption);
  initializeInputTree(PosDepOpts);
  initializeInputOutput(info);
  // Now, all input arguments are prepared well, send it into MCLDDriver
  m_pLDDriver = new MCLDDriver(info, *m_pLDBackend);

  return false;
}

bool SectLinker::doFinalization(Module &pM)
{
  const MCLDInfo &info = m_pOption->info();

  // 2. - initialize MCLinker
  if (!m_pLDDriver->initMCLinker())
    return true;

  // 3. - initialize output's standard sections
  if (!m_pLDDriver->initStdSections())
    return true;

  // 4. - normalize the input tree
  m_pLDDriver->normalize();

  if (info.options().trace()) {
    static int counter = 0;
    mcld::outs() << "** name\ttype\tpath\tsize (" << info.inputs().size() << ")\n";
    InputTree::const_dfs_iterator input, inEnd = info.inputs().dfs_end();
    for (input=info.inputs().dfs_begin(); input!=inEnd; ++input) {
      mcld::outs() << counter++ << " *  " << (*input)->name();
      switch((*input)->type()) {
      case Input::Archive:
        mcld::outs() << "\tarchive\t(";
        break;
      case Input::Object:
        mcld::outs() << "\tobject\t(";
        break;
      case Input::DynObj:
        mcld::outs() << "\tshared\t(";
        break;
      case Input::Script:
        mcld::outs() << "\tscript\t(";
        break;
      case Input::External:
        mcld::outs() << "\textern\t(";
        break;
      default:
        unreachable(diag::err_cannot_trace_file) << (*input)->type()
                                                 << (*input)->name()
                                                 << (*input)->path();
      }
      mcld::outs() << (*input)->path() << ")\n";
    }
  }

  // 5. - check if we can do static linking and if we use split-stack.
  if (!m_pLDDriver->linkable())
    return true;


  // 6. - read all sections
  if (!m_pLDDriver->readSections() ||
      !m_pLDDriver->mergeSections())
    return true;

  // 7. - read all symbol tables of input files and resolve them
  if (!m_pLDDriver->readSymbolTables())
    return true;

  // 7.a - add standard symbols and target-dependent symbols
  // m_pLDDriver->addUndefSymbols();
  if (!m_pLDDriver->addStandardSymbols() ||
      !m_pLDDriver->addTargetSymbols())
    return true;

  // 8. - read all relocation entries from input files
  m_pLDDriver->readRelocations();

  // 9. - pre-layout
  m_pLDDriver->prelayout();

  // 10. - linear layout
  m_pLDDriver->layout();

  // 10.b - post-layout
  m_pLDDriver->postlayout();

  // 11. - finalize symbol value
  m_pLDDriver->finalizeSymbolValue();

  // 12. - apply relocations
  m_pLDDriver->relocation();

  // 13. - write out output
  m_pLDDriver->emitOutput();

  // 14. - post processing
  m_pLDDriver->postProcessing();
  return false;
}

bool SectLinker::runOnMachineFunction(MachineFunction& pF)
{
  // basically, linkers do nothing during function is generated.
  return false;
}

void SectLinker::initializeInputOutput(MCLDInfo &pLDInfo)
{
  // -----  initialize output file  ----- //
  FileHandle::Permission perm;
  if (Output::Object == pLDInfo.output().type())
    perm = 0544;
  else
    perm = 0755;

  MemoryArea* out_area = memAreaFactory()->produce(pLDInfo.output().path(),
                                                 FileHandle::ReadWrite,
                                                 perm);

  if (!out_area->handler()->isGood()) {
    // make sure output is openend successfully.
    fatal(diag::err_cannot_open_output_file) << pLDInfo.output().name()
                                             << pLDInfo.output().path();
  }

  pLDInfo.output().setMemArea(out_area);
  pLDInfo.output().setContext(pLDInfo.contextFactory().produce());

  // -----  initialize input files  ----- //
  InputTree::dfs_iterator input, inEnd = pLDInfo.inputs().dfs_end();
  for (input = pLDInfo.inputs().dfs_begin(); input!=inEnd; ++input) {
    // already got type - for example, bitcode
    if ((*input)->type() == Input::Script ||
        (*input)->type() == Input::Object ||
        (*input)->type() == Input::DynObj  ||
        (*input)->type() == Input::Archive)
      continue;

    MemoryArea *input_memory =
        memAreaFactory()->produce((*input)->path(), FileHandle::ReadOnly);

    if (input_memory->handler()->isGood()) {
      (*input)->setMemArea(input_memory);
    }
    else {
      error(diag::err_cannot_open_input) << (*input)->name() << (*input)->path();
      return;
    }

    LDContext *input_context =
        pLDInfo.contextFactory().produce((*input)->path());

    (*input)->setContext(input_context);
  }
}

void SectLinker::initializeInputTree(const PositionDependentOptions &pPosDepOptions) const
{
  if (pPosDepOptions.empty())
    fatal(diag::err_no_inputs);

  MCLDInfo &info = m_pOption->info();
  PositionDependentOptions::const_iterator option = pPosDepOptions.begin();
  if (1 == pPosDepOptions.size() &&
      ((*option)->type() != PositionDependentOption::INPUT_FILE &&
       (*option)->type() != PositionDependentOption::NAMESPEC) &&
       (*option)->type() != PositionDependentOption::BITCODE) {
    // if we only have one positional options, and the option is
    // not an input file, then emit error message.
    fatal(diag::err_no_inputs);
  }

  // -----  Input tree insertion algorithm  ----- //
  //   The type of the previsou node indicates the direction of the current
  //   insertion.
  //
  //     root   : the parent node who being inserted.
  //     mover  : the direcion of current movement.
  //
  //   for each positional options:
  //     insert the options in current root.
  //     calculate the next movement

  // Initialization
  InputTree::Mover *move = &InputTree::Downward;
  InputTree::iterator root = info.inputs().root();
  PositionDependentOptions::const_iterator optionEnd = pPosDepOptions.end();
  std::stack<InputTree::iterator> returnStack;

  while (option != optionEnd ) {

    switch ((*option)->type()) {
      /** bitcode **/
      case PositionDependentOption::BITCODE: {

        const BitcodeOption *bitcode_option =
            static_cast<const BitcodeOption*>(*option);

        // threat bitcode as an external IR in this version.
        info.inputs().insert(root, *move,
                             bitcode_option->path()->native(),
                             *(bitcode_option->path()),
                             Input::External);

        info.setBitcode(**root);

        // move root on the new created node.
        move->move(root);

        // the next file is appended after bitcode file.
        move = &InputTree::Afterward;
        break;
      }

      /** input object file **/
      case PositionDependentOption::INPUT_FILE: {
        const InputFileOption *input_file_option =
            static_cast<const InputFileOption*>(*option);

        info.inputs().insert(root, *move,
                             input_file_option->path()->native(),
                             *(input_file_option->path()));

        // move root on the new created node.
        move->move(root);

        // the next file is appended after object file.
        move = &InputTree::Afterward;
        break;
      }

    /** -lnamespec **/
    case PositionDependentOption::NAMESPEC: {
      sys::fs::Path* path = NULL;
      const NamespecOption *namespec_option =
          static_cast<const NamespecOption*>(*option);

      // find out the real path of the namespec.
      if (info.attrFactory().constraint().isSharedSystem()) {
        // In the system with shared object support, we can find both archive
        // and shared object.

        if (info.attrFactory().last().isStatic()) {
          // with --static, we must search an archive.
          path = info.options().directories().find(namespec_option->namespec(),
                                                   Input::Archive);
        }
        else {
          // otherwise, with --Bdynamic, we can find either an archive or a
          // shared object.
          path = info.options().directories().find(namespec_option->namespec(),
                                                   Input::DynObj);
        }
      }
      else {
        // In the system without shared object support, we only look for an
        // archive.
        path = info.options().directories().find(namespec_option->namespec(),
                                                 Input::Archive);
      }

      if (NULL == path)
        fatal(diag::err_cannot_find_namespec) << namespec_option->namespec();

      info.inputs().insert(root, *move,
                           namespec_option->namespec(),
                           *path);

      // iterate root on the new created node.
      move->move(root);

      // the file after a namespec must be appended afterward.
      move = &InputTree::Afterward;
      break;
    }

    /** start group **/
    case PositionDependentOption::START_GROUP:
      info.inputs().enterGroup(root, *move);
      move->move(root);
      returnStack.push(root);
      move = &InputTree::Downward;
      break;
    /** end group **/
    case PositionDependentOption::END_GROUP:
      root = returnStack.top();
      returnStack.pop();
      move = &InputTree::Afterward;
      break;
    case PositionDependentOption::WHOLE_ARCHIVE:
      info.attrFactory().last().setWholeArchive();
      break;
    case PositionDependentOption::NO_WHOLE_ARCHIVE:
      info.attrFactory().last().unsetWholeArchive();
      break;
    case PositionDependentOption::AS_NEEDED:
      info.attrFactory().last().setAsNeeded();
      break;
    case PositionDependentOption::NO_AS_NEEDED:
      info.attrFactory().last().unsetAsNeeded();
      break;
    case PositionDependentOption::ADD_NEEDED:
      info.attrFactory().last().setAddNeeded();
      break;
    case PositionDependentOption::NO_ADD_NEEDED:
      info.attrFactory().last().unsetAddNeeded();
      break;
    case PositionDependentOption::BSTATIC:
      info.attrFactory().last().setStatic();
      break;
    case PositionDependentOption::BDYNAMIC:
      info.attrFactory().last().setDynamic();
      break;
    default:
      fatal(diag::err_cannot_identify_option) << (*option)->position()
                                              << (uint32_t)(*option)->type();
    } // end of switch
    ++option;
  } // end of while

  if (!returnStack.empty()) {
    report_fatal_error("no matched --start-group and --end-group");
  }
}

//===----------------------------------------------------------------------===//
// Non-member functions
static bool CompareOption(const PositionDependentOption* X,
                          const PositionDependentOption* Y)
{
  return (X->position() < Y->position());
}

