//===- Main.cpp -----------------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <mcld/Environment.h>
#include <mcld/IRBuilder.h>
#include <mcld/Linker.h>
#include <mcld/LinkerConfig.h>
#include <mcld/LinkerScript.h>
#include <mcld/Module.h>
#include <mcld/ADT/StringEntry.h>
#include <mcld/MC/InputAction.h>
#include <mcld/MC/CommandAction.h>
#include <mcld/MC/FileAction.h>
#include <mcld/MC/ZOption.h>
#include <mcld/Support/raw_ostream.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Support/Path.h>
#include <mcld/Support/SystemUtils.h>
#include <mcld/Support/TargetRegistry.h>

#include <llvm/ADT/ArrayRef.h>
#include <llvm/ADT/SmallVector.h>
#include <llvm/ADT/STLExtras.h>
#include <llvm/ADT/StringRef.h>
#include <llvm/ADT/StringSwitch.h>
#include <llvm/Option/Arg.h>
#include <llvm/Option/ArgList.h>
#include <llvm/Option/OptTable.h>
#include <llvm/Option/Option.h>
#include <llvm/Support/ManagedStatic.h>
#include <llvm/Support/Process.h>
#include <llvm/Support/Signals.h>

#include <cassert>
#include <cstdlib>
#include <string>

#if defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif

#if defined(_MSC_VER) || defined(__MINGW32__)
#include <io.h>
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
#endif

namespace {

class Driver {
 private:
  enum Option {
    // This is not an option.
    kOpt_INVALID = 0,
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
               HELPTEXT, METAVAR) \
    kOpt_ ## ID,
#include "Options.inc"  // NOLINT
#undef OPTION
    kOpt_LastOption
  };

  class OptTable : public llvm::opt::OptTable {
   private:
#define PREFIX(NAME, VALUE) \
    static const char* const NAME[];
#include "Options.inc"  // NOLINT
#undef PREFIX
    static const llvm::opt::OptTable::Info InfoTable[];

   public:
    OptTable();
  };

 private:
  Driver(const char* prog_name, std::unique_ptr<llvm::opt::InputArgList> args)
      : prog_name_(prog_name),
        args_(std::move(args)),
        module_(script_),
        ir_builder_(module_, config_) {
    return;
  }

 public:
  static std::unique_ptr<Driver> Create(llvm::ArrayRef<const char*> argv);

  bool Run();

 private:
  bool TranslateArguments();

 private:
  const char* prog_name_;

  std::unique_ptr<llvm::opt::InputArgList> args_;

  mcld::LinkerScript script_;

  mcld::LinkerConfig config_;

  mcld::Module module_;

  mcld::IRBuilder ir_builder_;

  mcld::Linker linker_;

 private:
  DISALLOW_COPY_AND_ASSIGN(Driver);
};

#define PREFIX(NAME, VALUE) \
    const char* const Driver::OptTable::NAME[] = VALUE;
#include "Options.inc"  // NOLINT
#undef PREFIX

const llvm::opt::OptTable::Info Driver::OptTable::InfoTable[] = {
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
               HELPTEXT, METAVAR) \
    { PREFIX, NAME, HELPTEXT, METAVAR, kOpt_ ## ID, \
      llvm::opt::Option::KIND ## Class, PARAM, FLAGS, kOpt_ ## GROUP, \
      kOpt_ ## ALIAS, ALIASARGS },
#include "Options.inc"
#undef OPTION
};

Driver::OptTable::OptTable()
    : llvm::opt::OptTable(InfoTable, llvm::array_lengthof(InfoTable)) { }

inline bool ShouldColorize() {
  const char* term = getenv("TERM");
  return term && (0 != strcmp(term, "dumb"));
}

/// ParseProgName - Parse program name
/// This function simplifies cross-compiling by reading triple from the program
/// name. For example, if the program name is `arm-linux-eabi-ld.mcld', we can
/// get the triple is arm-linux-eabi by the program name.
inline std::string ParseProgName(const char* prog_name) {
  static const char* suffixes[] = {"ld", "ld.mcld"};

  std::string name(mcld::sys::fs::Path(prog_name).stem().native());

  for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
    if (name == suffixes[i])
      return std::string();
  }

  llvm::StringRef prog_name_ref(prog_name);
  llvm::StringRef prefix;

  for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
    if (!prog_name_ref.endswith(suffixes[i]))
      continue;

    llvm::StringRef::size_type last_component =
        prog_name_ref.rfind('-', prog_name_ref.size() - strlen(suffixes[i]));
    if (last_component == llvm::StringRef::npos)
      continue;
    llvm::StringRef prefix = prog_name_ref.slice(0, last_component);
    std::string ignored_error;
    if (!mcld::TargetRegistry::lookupTarget(prefix, ignored_error))
      continue;
    return prefix.str();
  }
  return std::string();
}

inline void ParseEmulation(llvm::Triple& triple, const char* emulation) {
  llvm::Triple emu_triple =
      llvm::StringSwitch<llvm::Triple>(emulation)
          .Case("aarch64linux", llvm::Triple("aarch64", "", "linux", "gnu"))
          .Case("armelf_linux_eabi", llvm::Triple("arm", "", "linux", "gnu"))
          .Case("elf_i386", llvm::Triple("i386", "", "", "gnu"))
          .Case("elf_x86_64", llvm::Triple("x86_64", "", "", "gnu"))
          .Case("elf32_x86_64", llvm::Triple("x86_64", "", "", "gnux32"))
          .Case("elf_i386_fbsd", llvm::Triple("i386", "", "freebsd", "gnu"))
          .Case("elf_x86_64_fbsd", llvm::Triple("x86_64", "", "freebsd", "gnu"))
          .Case("elf32ltsmip", llvm::Triple("mipsel", "", "", "gnu"))
          .Case("elf64ltsmip", llvm::Triple("mips64el", "", "", "gnu"))
          .Default(llvm::Triple());

  if (emu_triple.getArch() == llvm::Triple::UnknownArch &&
      emu_triple.getOS() == llvm::Triple::UnknownOS &&
      emu_triple.getEnvironment() == llvm::Triple::UnknownEnvironment)
    mcld::error(mcld::diag::err_invalid_emulation) << emulation << "\n";

  if (emu_triple.getArch() != llvm::Triple::UnknownArch)
    triple.setArch(emu_triple.getArch());

  if (emu_triple.getOS() != llvm::Triple::UnknownOS)
    triple.setOS(emu_triple.getOS());

  if (emu_triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
    triple.setEnvironment(emu_triple.getEnvironment());
}

/// Configure the output filename.
inline bool ConfigureOutputName(llvm::StringRef output_name,
                                mcld::Module& module,
                                mcld::LinkerConfig& config) {
  std::string output(output_name.str());
  if (output.empty()) {
    if (config.targets().triple().getOS() == llvm::Triple::Win32) {
      output.assign("_out");
      switch (config.codeGenType()) {
        case mcld::LinkerConfig::Object: {
          output += ".obj";
          break;
        }
        case mcld::LinkerConfig::DynObj: {
          output += ".dll";
          break;
        }
        case mcld::LinkerConfig::Exec: {
          output += ".exe";
          break;
        }
        case mcld::LinkerConfig::External:
          break;
        default: {
          return false;
          break;
        }
      }  // switch (config.codeGenType())
    } else {
      output.assign("a.out");
    }
  }  // if (output.empty())

  module.setName(output);
  return true;
}

bool InitializeInputs(mcld::IRBuilder& ir_builder,
    std::vector<std::unique_ptr<mcld::InputAction>>& input_actions) {
  for (auto& action : input_actions) {
    assert(action != nullptr);
    action->activate(ir_builder.getInputBuilder());
  }

  if (ir_builder.getInputBuilder().isInGroup()) {
    mcld::fatal(mcld::diag::fatal_forbid_nest_group);
    return false;
  }

  return true;
}

bool Driver::TranslateArguments() {
  //===--------------------------------------------------------------------===//
  // Preference
  //===--------------------------------------------------------------------===//

  // --color=mode
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_Color)) {
    bool res = llvm::StringSwitch<bool>(arg->getValue())
                   .Case("never", false)
                   .Case("always", true)
                   .Case("auto", ShouldColorize() &&
                                 llvm::sys::Process::FileDescriptorIsDisplayed(
                                     STDOUT_FILENO))
                   .Default(false);
    config_.options().setColor(res);
    mcld::outs().setColor(res);
    mcld::errs().setColor(res);
  }

  // --trace
  config_.options().setTrace(args_->hasArg(kOpt_Trace));

  // --verbose=level
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_Verbose)) {
    llvm::StringRef value = arg->getValue();
    int level;
    if (value.getAsInteger(0, level)) {
      mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
                   << ": " << arg->getValue();
      return false;
    }
    config_.options().setVerbose(level);
  }

  // --error-limit NUMBER
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_ErrorLimit)) {
    llvm::StringRef value = arg->getValue();
    int num;
    if (value.getAsInteger(0, num) || (num < 0)) {
      mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
                   << ": " << arg->getValue();
      return false;
    }
    config_.options().setMaxErrorNum(num);
  }

  // --warning-limit NUMBER
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_WarningLimit)) {
    llvm::StringRef value = arg->getValue();
    int num;
    if (value.getAsInteger(0, num) || (num < 0)) {
      mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
                   << ": " << arg->getValue();
      return false;
    }
    config_.options().setMaxWarnNum(num);
  }

  // --warn-shared-textrel
  config_.options().setWarnSharedTextrel(args_->hasArg(kOpt_WarnSharedTextrel));

  //===--------------------------------------------------------------------===//
  // Target
  //===--------------------------------------------------------------------===//
  llvm::Triple triple;
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_Triple)) {
    // 1. Use the triple from command.
    // -mtriple=value
    triple.setTriple(arg->getValue());
  } else {
    std::string prog_triple = ParseProgName(prog_name_);
    if (!prog_triple.empty()) {
      // 2. Use the triple from the program name prefix.
      triple.setTriple(prog_triple);
    } else {
      // 3. Use the default target triple.
      triple.setTriple(mcld::sys::getDefaultTargetTriple());
    }
  }

  // If a specific emulation was requested, apply it now.
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_Emulation)) {
    // -m emulation
    ParseEmulation(triple, arg->getValue());
  } else if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_Arch)) {
    // -march=value
    config_.targets().setArch(arg->getValue());
  }

  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_CPU)) {
    config_.targets().setTargetCPU(arg->getValue());
  }

  config_.targets().setTriple(triple);

  // --gpsize=value
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_GPSize)) {
    llvm::StringRef value = arg->getValue();
    int size;
    if (value.getAsInteger(0, size) || (size< 0)) {
      mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
                   << ": " << arg->getValue() << "\n";
      return false;
    }
    config_.options().setGPSize(size);
  }

  //===--------------------------------------------------------------------===//
  // Dynamic
  //===--------------------------------------------------------------------===//

  // --entry=entry
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_Entry)) {
    script_.setEntry(arg->getValue());
  }

  // -Bsymbolic
  config_.options().setBsymbolic(args_->hasArg(kOpt_Bsymbolic));

  // -Bgroup
  config_.options().setBgroup(args_->hasArg(kOpt_Bgroup));

  // -soname=name
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_SOName)) {
    config_.options().setSOName(arg->getValue());
  }

  // --no-undefined
  if (args_->hasArg(kOpt_NoUndef)) {
    config_.options().setNoUndefined(true);
  }

  // --allow-multiple-definition
  if (args_->hasArg(kOpt_AllowMulDefs)) {
    config_.options().setMulDefs(true);
  }

  // -z options
  for (llvm::opt::Arg* arg : args_->filtered(kOpt_Z)) {
    llvm::StringRef value = arg->getValue();
    mcld::ZOption z_opt =
        llvm::StringSwitch<mcld::ZOption>(value)
            .Case("combreloc", mcld::ZOption(mcld::ZOption::CombReloc))
            .Case("nocombreloc", mcld::ZOption(mcld::ZOption::NoCombReloc))
            .Case("defs", mcld::ZOption(mcld::ZOption::Defs))
            .Case("execstack", mcld::ZOption(mcld::ZOption::ExecStack))
            .Case("noexecstack", mcld::ZOption(mcld::ZOption::NoExecStack))
            .Case("initfirst", mcld::ZOption(mcld::ZOption::InitFirst))
            .Case("interpose", mcld::ZOption(mcld::ZOption::InterPose))
            .Case("loadfltr", mcld::ZOption(mcld::ZOption::LoadFltr))
            .Case("muldefs", mcld::ZOption(mcld::ZOption::MulDefs))
            .Case("nocopyreloc", mcld::ZOption(mcld::ZOption::NoCopyReloc))
            .Case("nodefaultlib", mcld::ZOption(mcld::ZOption::NoDefaultLib))
            .Case("nodelete", mcld::ZOption(mcld::ZOption::NoDelete))
            .Case("nodlopen", mcld::ZOption(mcld::ZOption::NoDLOpen))
            .Case("nodump", mcld::ZOption(mcld::ZOption::NoDump))
            .Case("relro", mcld::ZOption(mcld::ZOption::Relro))
            .Case("norelro", mcld::ZOption(mcld::ZOption::NoRelro))
            .Case("lazy", mcld::ZOption(mcld::ZOption::Lazy))
            .Case("now", mcld::ZOption(mcld::ZOption::Now))
            .Case("origin", mcld::ZOption(mcld::ZOption::Origin))
            .Default(mcld::ZOption());

    if (z_opt.kind() == mcld::ZOption::Unknown) {
      if (value.startswith("common-page-size=")) {
        // -z common-page-size=value
        z_opt.setKind(mcld::ZOption::CommPageSize);
        long long unsigned size = 0;
        value.drop_front(17).getAsInteger(0, size);
        z_opt.setPageSize(static_cast<uint64_t>(size));
      } else if (value.startswith("max-page-size=")) {
        // -z max-page-size=value
        z_opt.setKind(mcld::ZOption::MaxPageSize);
        long long unsigned size = 0;
        value.drop_front(14).getAsInteger(0, size);
        z_opt.setPageSize(static_cast<uint64_t>(size));
      }
    }
    config_.options().addZOption(z_opt);
  }

  // --dynamic-linker=file
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_Dyld)) {
    config_.options().setDyld(arg->getValue());
  }

  // --enable-new-dtags
  config_.options().setNewDTags(args_->hasArg(kOpt_EnableNewDTags));

  // --spare-dyanmic-tags COUNT
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_SpareDTags)) {
    llvm::StringRef value = arg->getValue();
    int num;
    if (value.getAsInteger(0, num) || (num < 0)) {
      mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
                   << ": " << arg->getValue() << "\n";
      return false;
    }
    config_.options().setNumSpareDTags(num);
  }

  //===--------------------------------------------------------------------===//
  // Output
  //===--------------------------------------------------------------------===//

  // Setup the codegen type.
  if (args_->hasArg(kOpt_Shared) || args_->hasArg(kOpt_PIE)) {
    // -shared, -pie
    config_.setCodeGenType(mcld::LinkerConfig::DynObj);
  } else if (args_->hasArg(kOpt_Relocatable)) {
    // -r
    config_.setCodeGenType(mcld::LinkerConfig::Object);
  } else if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_OutputFormat)) {
    // --oformat=value
    llvm::StringRef value = arg->getValue();
    if (value.equals("binary")) {
      config_.setCodeGenType(mcld::LinkerConfig::Binary);
    }
  } else {
    config_.setCodeGenType(mcld::LinkerConfig::Exec);
  }

  // Setup the output filename.
  llvm::StringRef output_name;
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_Output)) {
    output_name = arg->getValue();
  }
  if (!ConfigureOutputName(output_name, module_, config_)) {
    mcld::unreachable(mcld::diag::unrecognized_output_file) << module_.name();
    return false;
  } else {
    if (!args_->hasArg(kOpt_SOName)) {
      config_.options().setSOName(module_.name());
    }
  }

  // --format=value
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_InputFormat)) {
    llvm::StringRef value = arg->getValue();
    if (value.equals("binary")) {
      config_.options().setBinaryInput();
    }
  }

  // Setup debug info stripping.
  config_.options().setStripDebug(args_->hasArg(kOpt_StripDebug) ||
                                  args_->hasArg(kOpt_StripAll));

  // Setup symbol stripping mode.
  if (args_->hasArg(kOpt_StripAll)) {
    config_.options().setStripSymbols(
        mcld::GeneralOptions::StripSymbolMode::StripAllSymbols);
  } else if (args_->hasArg(kOpt_DiscardAll)) {
    config_.options().setStripSymbols(
        mcld::GeneralOptions::StripSymbolMode::StripLocals);
  } else if (args_->hasArg(kOpt_DiscardLocals)) {
    config_.options().setStripSymbols(
        mcld::GeneralOptions::StripSymbolMode::StripTemporaries);
  } else {
    config_.options().setStripSymbols(
        mcld::GeneralOptions::StripSymbolMode::KeepAllSymbols);
  }

  // --eh-frame-hdr
  config_.options().setEhFrameHdr(args_->hasArg(kOpt_EHFrameHdr));

  // -pie
  config_.options().setPIE(args_->hasArg(kOpt_PIE));

  // --nmagic
  config_.options().setNMagic(args_->hasArg(kOpt_NMagic));

  // --omagic
  config_.options().setOMagic(args_->hasArg(kOpt_OMagic));

  // --hash-style=style
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_HashStyle)) {
    mcld::GeneralOptions::HashStyle style =
        llvm::StringSwitch<mcld::GeneralOptions::HashStyle>(arg->getValue())
            .Case("sysv", mcld::GeneralOptions::HashStyle::SystemV)
            .Case("gnu", mcld::GeneralOptions::HashStyle::GNU)
            .Case("both", mcld::GeneralOptions::HashStyle::Both)
            .Default(mcld::GeneralOptions::HashStyle::Unknown);
    if (style != mcld::GeneralOptions::HashStyle::Unknown) {
      config_.options().setHashStyle(style);
    }
  }

  // --[no]-export-dynamic
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_ExportDynamic,
                                              kOpt_NoExportDynamic)) {
    if (arg->getOption().matches(kOpt_ExportDynamic)) {
      config_.options().setExportDynamic(true);
    } else {
      config_.options().setExportDynamic(false);
    }
  }

  // --no-warn-mismatch
  config_.options().setWarnMismatch(!args_->hasArg(kOpt_NoWarnMismatch));

  // --exclude-libs
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_ExcludeLibs)) {
    llvm::StringRef value = arg->getValue();
    do {
      std::pair<llvm::StringRef, llvm::StringRef> res = value.split(',');
      config_.options().excludeLIBS().insert(res.first.str());
      value = res.second;
    } while (!value.empty());
  }

  //===--------------------------------------------------------------------===//
  // Search Path
  //===--------------------------------------------------------------------===//

  // --sysroot
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_Sysroot)) {
    mcld::sys::fs::Path path(arg->getValue());
    if (mcld::sys::fs::exists(path) && mcld::sys::fs::is_directory(path)) {
      script_.setSysroot(path);
    }
  }

  // -L searchdir
  for (llvm::opt::Arg* arg : args_->filtered(kOpt_LibraryPath)) {
    if (!script_.directories().insert(arg->getValue())) {
      // FIXME: need a warning function
      mcld::errs() << "WARNING: can not open search directory `-L"
                   << arg->getValue() << "'.\n";
    }
  }

  // -nostdlib
  config_.options().setNoStdlib(args_->hasArg(kOpt_NoStdlib));

  // -rpath=path
  for (llvm::opt::Arg* arg : args_->filtered(kOpt_RPath)) {
    config_.options().getRpathList().push_back(arg->getValue());
  }

  //===--------------------------------------------------------------------===//
  // Symbol
  //===--------------------------------------------------------------------===//

  // -d/-dc/-dp
  config_.options().setDefineCommon(args_->hasArg(kOpt_DefineCommon));

  // -u symbol
  for (llvm::opt::Arg* arg : args_->filtered(kOpt_Undefined)) {
    config_.options().getUndefSymList().push_back(arg->getValue());
  }

  //===--------------------------------------------------------------------===//
  // Script
  //===--------------------------------------------------------------------===//

  // --wrap=symbol
  for (llvm::opt::Arg* arg : args_->filtered(kOpt_Wrap)) {
    bool exist = false;
    const char* symbol = arg->getValue();
    // symbol -> __wrap_symbol
    mcld::StringEntry<llvm::StringRef>* to_wrap =
        script_.renameMap().insert(symbol, exist);

    std::string to_wrap_str;
    to_wrap_str.append("__wrap_")
               .append(symbol);
    to_wrap->setValue(to_wrap_str);

    if (exist)
      mcld::warning(mcld::diag::rewrap) << symbol << to_wrap_str;

    // __real_symbol -> symbol
    std::string from_real_str;
    to_wrap_str.append("__real_")
               .append(symbol);
    mcld::StringEntry<llvm::StringRef>* from_real =
        script_.renameMap().insert(from_real_str, exist);
    from_real->setValue(symbol);

    if (exist)
      mcld::warning(mcld::diag::rewrap) << symbol << from_real_str;
  }

  // --portalbe=symbol
  for (llvm::opt::Arg* arg : args_->filtered(kOpt_Wrap)) {
    bool exist = false;
    const char* symbol = arg->getValue();
    // symbol -> symbol_portable
    mcld::StringEntry<llvm::StringRef>* to_wrap =
        script_.renameMap().insert(symbol, exist);

    std::string to_wrap_str;
    to_wrap_str.append(symbol)
               .append("_portable");
    to_wrap->setValue(to_wrap_str);

    if (exist)
      mcld::warning(mcld::diag::rewrap) << symbol << to_wrap_str;

    // __real_symbol -> symbol
    std::string from_real_str;
    to_wrap_str.append("__real_")
               .append(symbol);
    mcld::StringEntry<llvm::StringRef>* from_real =
        script_.renameMap().insert(from_real_str, exist);
    from_real->setValue(symbol);

    if (exist)
      mcld::warning(mcld::diag::rewrap) << symbol << from_real_str;
  }

  // --section-start=section=addr
  for (llvm::opt::Arg* arg : args_->filtered(kOpt_SectionStart)) {
    llvm::StringRef value = arg->getValue();
    const size_t pos = value.find('=');
    uint64_t addr = 0;
    value.substr(pos + 1).getAsInteger(0, addr);
    bool exist = false;
    mcld::StringEntry<uint64_t>* mapping =
        script_.addressMap().insert(value.substr(0, pos), exist);
    mapping->setValue(addr);
  }

  // -Tbss=value
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_Tbss)) {
    llvm::StringRef value = arg->getValue();
    uint64_t addr = 0;
    if (value.getAsInteger(0, addr)) {
      mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
                   << ": " << arg->getValue() << "\n";
      return false;
    }
    bool exist = false;
    mcld::StringEntry<uint64_t>* mapping =
        script_.addressMap().insert(".bss", exist);
    mapping->setValue(addr);
  }

  // -Tdata=value
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_Tdata)) {
    llvm::StringRef value = arg->getValue();
    uint64_t addr = 0;
    if (value.getAsInteger(0, addr)) {
      mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
                   << ": " << arg->getValue() << "\n";
      return false;
    }
    bool exist = false;
    mcld::StringEntry<uint64_t>* mapping =
        script_.addressMap().insert(".data", exist);
    mapping->setValue(addr);
  }

  // -Ttext=value
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_Ttext)) {
    llvm::StringRef value = arg->getValue();
    uint64_t addr = 0;
    if (value.getAsInteger(0, addr)) {
      mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
                   << ": " << arg->getValue() << "\n";
      return false;
    }
    bool exist = false;
    mcld::StringEntry<uint64_t>* mapping =
        script_.addressMap().insert(".text", exist);
    mapping->setValue(addr);
  }

  //===--------------------------------------------------------------------===//
  // Optimization
  //===--------------------------------------------------------------------===//

  // --[no-]gc-sections
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_GCSections,
                                              kOpt_NoGCSections)) {
    if (arg->getOption().matches(kOpt_GCSections)) {
      config_.options().setGCSections(true);
    } else {
      config_.options().setGCSections(false);
    }
  }

  // --[no-]print-gc-sections
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_PrintGCSections,
                                              kOpt_NoPrintGCSections)) {
    if (arg->getOption().matches(kOpt_PrintGCSections)) {
      config_.options().setPrintGCSections(true);
    } else {
      config_.options().setPrintGCSections(false);
    }
  }

  // --[no-]ld-generated-unwind-info
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_LDGeneratedUnwindInfo,
                                              kOpt_NoLDGeneratedUnwindInfo)) {
    if (arg->getOption().matches(kOpt_LDGeneratedUnwindInfo)) {
      config_.options().setGenUnwindInfo(true);
    } else {
      config_.options().setGenUnwindInfo(false);
    }
  }

  // --icf=mode
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_ICF)) {
    mcld::GeneralOptions::ICF mode =
        llvm::StringSwitch<mcld::GeneralOptions::ICF>(arg->getValue())
            .Case("none", mcld::GeneralOptions::ICF::None)
            .Case("all", mcld::GeneralOptions::ICF::All)
            .Case("safe", mcld::GeneralOptions::ICF::Safe)
            .Default(mcld::GeneralOptions::ICF::Unknown);
    if (mode == mcld::GeneralOptions::ICF::Unknown) {
      mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
                   << ": " << arg->getValue() << "\n";
      return false;
    }
    config_.options().setICFMode(mode);
  }

  // --icf-iterations
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_ICFIters)) {
    llvm::StringRef value = arg->getValue();
    int num;
    if (value.getAsInteger(0, num) || (num < 0)) {
      mcld::errs() << "Invalid value for" << arg->getOption().getPrefixedName()
                   << ": " << arg->getValue() << "\n";
      return false;
    }
    config_.options().setICFIterations(num);
  }

  // --[no-]print-icf-sections
  if (llvm::opt::Arg* arg = args_->getLastArg(kOpt_PrintICFSections,
                                              kOpt_NoPrintICFSections)) {
    if (arg->getOption().matches(kOpt_PrintICFSections)) {
      config_.options().setPrintICFSections(true);
    } else {
      config_.options().setPrintICFSections(false);
    }
  }

  //===--------------------------------------------------------------------===//
  // Positional
  //===--------------------------------------------------------------------===//

  // # of regular objects, script, and namespec.
  size_t input_num = 0;
  typedef std::unique_ptr<mcld::InputAction> Action;

  std::vector<Action> actions;
  Action action;
  actions.reserve(32);

  for (llvm::opt::Arg* arg : *args_) {
    const unsigned index = arg->getIndex();

    switch (arg->getOption().getID()) {
      // -T script
      case kOpt_Script: {
        const char* value = arg->getValue();
        config_.options().getScriptList().push_back(value);

        // FIXME: Let index of script file be 0.
        action.reset(new mcld::ScriptAction(
            0x0, value, mcld::ScriptFile::LDScript, script_.directories()));
        actions.push_back(std::move(action));

        action.reset(new mcld::ContextAction(0x0));
        actions.push_back(std::move(action));

        action.reset(new mcld::MemoryAreaAction(0x0,
                                                mcld::FileHandle::ReadOnly));
        actions.push_back(std::move(action));

        ++input_num;
        break;
      }

      // --defsym=symbol=expr
      case kOpt_DefSym: {
        std::string expr;
        expr.append(arg->getValue())
            .append(";");
        script_.defsyms().push_back(std::move(expr));
        action.reset(new mcld::DefSymAction(index, script_.defsyms().back()));
        actions.push_back(std::move(action));
        break;
      }

      // -l namespec
      case kOpt_Namespec: {
        action.reset(new mcld::NamespecAction(
            index, arg->getValue(), script_.directories()));
        actions.push_back(std::move(action));

        action.reset(new mcld::ContextAction(index));
        actions.push_back(std::move(action));

        action.reset(new mcld::MemoryAreaAction(index,
                                                mcld::FileHandle::ReadOnly));
        actions.push_back(std::move(action));

        ++input_num;
        break;
      }

      // --whole-archive
      case kOpt_WholeArchive: {
        action.reset(new mcld::WholeArchiveAction(index));
        actions.push_back(std::move(action));
        break;
      }

      // --no-whole-archive
      case kOpt_NoWholeArchive: {
        action.reset(new mcld::NoWholeArchiveAction(index));
        actions.push_back(std::move(action));
        break;
      }

      // --as-needed
      case kOpt_AsNeeded: {
        action.reset(new mcld::AsNeededAction(index));
        actions.push_back(std::move(action));
        break;
      }

      // --no-as-needed
      case kOpt_NoAsNeeded: {
        action.reset(new mcld::NoAsNeededAction(index));
        actions.push_back(std::move(action));
        break;
      }

      // --add-needed
      // FIXME: This is deprecated. Should be --copy-dt-needed-entries.
      case kOpt_AddNeeded:
      case kOpt_CopyDTNeeded: {
        action.reset(new mcld::AddNeededAction(index));
        actions.push_back(std::move(action));
        break;
      }

      // --no-add-needed
      // FIXME: This is deprecated. Should be --no-copy-dt-needed-entries.
      case kOpt_NoAddNeeded:
      case kOpt_NoCopyDTNeeded: {
        action.reset(new mcld::AddNeededAction(index));
        actions.push_back(std::move(action));
        break;
      }

      // -Bdynamic
      case kOpt_Bdynamic: {
        action.reset(new mcld::BDynamicAction(index));
        actions.push_back(std::move(action));
        break;
      }

      // -Bstatic
      case kOpt_Bstatic: {
        action.reset(new mcld::BStaticAction(index));
        actions.push_back(std::move(action));
        break;
      }

      // --start-group
      case kOpt_StartGroup: {
        action.reset(new mcld::StartGroupAction(index));
        actions.push_back(std::move(action));
        break;
      }

      // --end-group
      case kOpt_EndGroup: {
        action.reset(new mcld::EndGroupAction(index));
        actions.push_back(std::move(action));
        break;
      }

      case kOpt_INPUT: {
        action.reset(new mcld::InputFileAction(index, arg->getValue()));
        actions.push_back(std::move(action));

        action.reset(new mcld::ContextAction(index));
        actions.push_back(std::move(action));

        action.reset(new mcld::MemoryAreaAction(index,
                                                mcld::FileHandle::ReadOnly));
        actions.push_back(std::move(action));

        ++input_num;
        break;
      }

      default:
        break;
    }
  }

  if (input_num == 0) {
    mcld::fatal(mcld::diag::err_no_inputs);
    return false;
  }

  // Stable sort
  std::stable_sort(actions.begin(),
                   actions.end(),
                   [] (const Action& X, const Action& Y) {
                     return X->position() < Y->position();
                   });

  if (!InitializeInputs(ir_builder_, actions)) {
    mcld::errs() << "Failed to initialize input tree!\n";
    return false;
  }

  return true;
}

std::unique_ptr<llvm::opt::InputArgList>
ParseArgs(const llvm::opt::OptTable& opt_table,
          llvm::ArrayRef<const char*> argv) {
  unsigned missing_arg_idx;
  unsigned missing_arg_count;

  std::unique_ptr<llvm::opt::InputArgList> args(
      opt_table.ParseArgs(argv.begin(), argv.end(), missing_arg_idx,
                          missing_arg_count));
  if (missing_arg_count > 0) {
    mcld::errs() << "Argument to '" << args->getArgString(missing_arg_idx)
                 << "' is missing (expected " << missing_arg_count
                 << ((missing_arg_count > 1) ? " values" : " value") << ")\n";
    return nullptr;
  }

  return args;
}

std::unique_ptr<Driver> Driver::Create(llvm::ArrayRef<const char*> argv) {
  // Parse command line options.
  OptTable opt_table;
  std::unique_ptr<llvm::opt::InputArgList> args = ParseArgs(opt_table,
                                                            argv.slice(1));
  if (args == nullptr) {
    return nullptr;
  }

  std::unique_ptr<Driver> result(new Driver(argv[0], std::move(args)));

  // Return quickly if -help is specified.
  if (result->args_->hasArg(kOpt_Help)) {
    opt_table.PrintHelp(mcld::outs(), argv[0], "MCLinker",
                        /* FlagsToInclude */0, /* FlagsToExclude */0);
    return nullptr;
  }

  // Print version information if requested.
  if (result->args_->hasArg(kOpt_Version)) {
    mcld::outs() << result->config_.options().getVersionString() << "\n";
  }

  // Setup instance from arguments.
  if (!result->TranslateArguments()) {
    return nullptr;
  }

  return result;
}

bool Driver::Run() {
  mcld::Initialize();

  if (!linker_.emulate(script_, config_)) {
    mcld::errs() << "Failed to emulate target!\n";
    return false;
  }

  if (!linker_.link(module_, ir_builder_)) {
    mcld::errs() << "Failed to link objects!\n";
    return false;
  }

  if (!linker_.emit(module_, module_.name())) {
    mcld::errs() << "Failed to emit output!\n";
    return false;
  }

  mcld::Finalize();
  return true;
}

}  // anonymous namespace

int main(int argc, char** argv) {
  std::unique_ptr<Driver> driver =
      Driver::Create(llvm::makeArrayRef(argv, argc));

  if ((driver == nullptr) || !driver->Run()) {
    return EXIT_FAILURE;
  } else {
    return EXIT_SUCCESS;
  }
}
