//===- Driver.cpp ---------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "Driver.h"
#include "Config.h"
#include "DebugTypes.h"
#include "ICF.h"
#include "InputFiles.h"
#include "MarkLive.h"
#include "MinGW.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "Writer.h"
#include "lld/Common/Args.h"
#include "lld/Common/Driver.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Filesystem.h"
#include "lld/Common/Memory.h"
#include "lld/Common/Threads.h"
#include "lld/Common/Timer.h"
#include "lld/Common/Version.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Object/COFFImportFile.h"
#include "llvm/Object/COFFModuleDefinition.h"
#include "llvm/Object/WindowsMachineFlag.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/TarWriter.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ToolDrivers/llvm-lib/LibDriver.h"
#include <algorithm>
#include <future>
#include <memory>

using namespace llvm;
using namespace llvm::object;
using namespace llvm::COFF;
using llvm::sys::Process;

namespace lld {
namespace coff {

static Timer InputFileTimer("Input File Reading", Timer::root());

Configuration *Config;
LinkerDriver *Driver;

bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) {
  errorHandler().LogName = args::getFilenameWithoutExe(Args[0]);
  errorHandler().ErrorOS = &Diag;
  errorHandler().ColorDiagnostics = Diag.has_colors();
  errorHandler().ErrorLimitExceededMsg =
      "too many errors emitted, stopping now"
      " (use /errorlimit:0 to see all errors)";
  errorHandler().ExitEarly = CanExitEarly;
  Config = make<Configuration>();

  Symtab = make<SymbolTable>();

  Driver = make<LinkerDriver>();
  Driver->link(Args);

  // Call exit() if we can to avoid calling destructors.
  if (CanExitEarly)
    exitLld(errorCount() ? 1 : 0);

  freeArena();
  ObjFile::Instances.clear();
  ImportFile::Instances.clear();
  BitcodeFile::Instances.clear();
  memset(MergeChunk::Instances, 0, sizeof(MergeChunk::Instances));
  return !errorCount();
}

// Drop directory components and replace extension with ".exe" or ".dll".
static std::string getOutputPath(StringRef Path) {
  auto P = Path.find_last_of("\\/");
  StringRef S = (P == StringRef::npos) ? Path : Path.substr(P + 1);
  const char* E = Config->DLL ? ".dll" : ".exe";
  return (S.substr(0, S.rfind('.')) + E).str();
}

// Returns true if S matches /crtend.?\.o$/.
static bool isCrtend(StringRef S) {
  if (!S.endswith(".o"))
    return false;
  S = S.drop_back(2);
  if (S.endswith("crtend"))
    return true;
  return !S.empty() && S.drop_back().endswith("crtend");
}

// ErrorOr is not default constructible, so it cannot be used as the type
// parameter of a future.
// FIXME: We could open the file in createFutureForFile and avoid needing to
// return an error here, but for the moment that would cost us a file descriptor
// (a limited resource on Windows) for the duration that the future is pending.
using MBErrPair = std::pair<std::unique_ptr<MemoryBuffer>, std::error_code>;

// Create a std::future that opens and maps a file using the best strategy for
// the host platform.
static std::future<MBErrPair> createFutureForFile(std::string Path) {
#if _WIN32
  // On Windows, file I/O is relatively slow so it is best to do this
  // asynchronously.
  auto Strategy = std::launch::async;
#else
  auto Strategy = std::launch::deferred;
#endif
  return std::async(Strategy, [=]() {
    auto MBOrErr = MemoryBuffer::getFile(Path,
                                         /*FileSize*/ -1,
                                         /*RequiresNullTerminator*/ false);
    if (!MBOrErr)
      return MBErrPair{nullptr, MBOrErr.getError()};
    return MBErrPair{std::move(*MBOrErr), std::error_code()};
  });
}

// Symbol names are mangled by prepending "_" on x86.
static StringRef mangle(StringRef Sym) {
  assert(Config->Machine != IMAGE_FILE_MACHINE_UNKNOWN);
  if (Config->Machine == I386)
    return Saver.save("_" + Sym);
  return Sym;
}

static bool findUnderscoreMangle(StringRef Sym) {
  Symbol *S = Symtab->findMangle(mangle(Sym));
  return S && !isa<Undefined>(S);
}

MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr<MemoryBuffer> MB) {
  MemoryBufferRef MBRef = *MB;
  make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take ownership

  if (Driver->Tar)
    Driver->Tar->append(relativeToRoot(MBRef.getBufferIdentifier()),
                        MBRef.getBuffer());
  return MBRef;
}

void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> MB,
                             bool WholeArchive) {
  StringRef Filename = MB->getBufferIdentifier();

  MemoryBufferRef MBRef = takeBuffer(std::move(MB));
  FilePaths.push_back(Filename);

  // File type is detected by contents, not by file extension.
  switch (identify_magic(MBRef.getBuffer())) {
  case file_magic::windows_resource:
    Resources.push_back(MBRef);
    break;
  case file_magic::archive:
    if (WholeArchive) {
      std::unique_ptr<Archive> File =
          CHECK(Archive::create(MBRef), Filename + ": failed to parse archive");

      for (MemoryBufferRef M : getArchiveMembers(File.get()))
        addArchiveBuffer(M, "<whole-archive>", Filename, 0);
      return;
    }
    Symtab->addFile(make<ArchiveFile>(MBRef));
    break;
  case file_magic::bitcode:
    Symtab->addFile(make<BitcodeFile>(MBRef, "", 0));
    break;
  case file_magic::coff_object:
  case file_magic::coff_import_library:
    Symtab->addFile(make<ObjFile>(MBRef));
    break;
  case file_magic::pdb:
    loadTypeServerSource(MBRef);
    break;
  case file_magic::coff_cl_gl_object:
    error(Filename + ": is not a native COFF file. Recompile without /GL");
    break;
  case file_magic::pecoff_executable:
    if (Filename.endswith_lower(".dll")) {
      error(Filename + ": bad file type. Did you specify a DLL instead of an "
                       "import library?");
      break;
    }
    LLVM_FALLTHROUGH;
  default:
    error(MBRef.getBufferIdentifier() + ": unknown file type");
    break;
  }
}

void LinkerDriver::enqueuePath(StringRef Path, bool WholeArchive) {
  auto Future =
      std::make_shared<std::future<MBErrPair>>(createFutureForFile(Path));
  std::string PathStr = Path;
  enqueueTask([=]() {
    auto MBOrErr = Future->get();
    if (MBOrErr.second) {
      std::string Error =
          "could not open '" + PathStr + "': " + MBOrErr.second.message();
      // Check if the filename is a typo for an option flag. OptTable thinks
      // that all args that are not known options and that start with / are
      // filenames, but e.g. `/nodefaultlibs` is more likely a typo for
      // the option `/nodefaultlib` than a reference to a file in the root
      // directory.
      std::string Nearest;
      if (COFFOptTable().findNearest(PathStr, Nearest) > 1)
        error(Error);
      else
        error(Error + "; did you mean '" + Nearest + "'");
    } else
      Driver->addBuffer(std::move(MBOrErr.first), WholeArchive);
  });
}

void LinkerDriver::addArchiveBuffer(MemoryBufferRef MB, StringRef SymName,
                                    StringRef ParentName,
                                    uint64_t OffsetInArchive) {
  file_magic Magic = identify_magic(MB.getBuffer());
  if (Magic == file_magic::coff_import_library) {
    InputFile *Imp = make<ImportFile>(MB);
    Imp->ParentName = ParentName;
    Symtab->addFile(Imp);
    return;
  }

  InputFile *Obj;
  if (Magic == file_magic::coff_object) {
    Obj = make<ObjFile>(MB);
  } else if (Magic == file_magic::bitcode) {
    Obj = make<BitcodeFile>(MB, ParentName, OffsetInArchive);
  } else {
    error("unknown file type: " + MB.getBufferIdentifier());
    return;
  }

  Obj->ParentName = ParentName;
  Symtab->addFile(Obj);
  log("Loaded " + toString(Obj) + " for " + SymName);
}

void LinkerDriver::enqueueArchiveMember(const Archive::Child &C,
                                        StringRef SymName,
                                        StringRef ParentName) {

  auto ReportBufferError = [=](Error &&E,
                              StringRef ChildName) {
    fatal("could not get the buffer for the member defining symbol " +
          SymName + ": " + ParentName + "(" + ChildName + "): " +
          toString(std::move(E)));
  };

  if (!C.getParent()->isThin()) {
    uint64_t OffsetInArchive = C.getChildOffset();
    Expected<MemoryBufferRef> MBOrErr = C.getMemoryBufferRef();
    if (!MBOrErr)
      ReportBufferError(MBOrErr.takeError(), check(C.getFullName()));
    MemoryBufferRef MB = MBOrErr.get();
    enqueueTask([=]() {
      Driver->addArchiveBuffer(MB, SymName, ParentName, OffsetInArchive);
    });
    return;
  }

  std::string ChildName = CHECK(
      C.getFullName(),
      "could not get the filename for the member defining symbol " +
      SymName);
  auto Future = std::make_shared<std::future<MBErrPair>>(
      createFutureForFile(ChildName));
  enqueueTask([=]() {
    auto MBOrErr = Future->get();
    if (MBOrErr.second)
      ReportBufferError(errorCodeToError(MBOrErr.second), ChildName);
    Driver->addArchiveBuffer(takeBuffer(std::move(MBOrErr.first)), SymName,
                             ParentName, /* OffsetInArchive */ 0);
  });
}

static bool isDecorated(StringRef Sym) {
  return Sym.startswith("@") || Sym.contains("@@") || Sym.startswith("?") ||
         (!Config->MinGW && Sym.contains('@'));
}

// Parses .drectve section contents and returns a list of files
// specified by /defaultlib.
void LinkerDriver::parseDirectives(InputFile *File) {
  StringRef S = File->getDirectives();
  if (S.empty())
    return;

  log("Directives: " + toString(File) + ": " + S);

  ArgParser Parser;
  // .drectve is always tokenized using Windows shell rules.
  // /EXPORT: option can appear too many times, processing in fastpath.
  opt::InputArgList Args;
  std::vector<StringRef> Exports;
  std::tie(Args, Exports) = Parser.parseDirectives(S);

  for (StringRef E : Exports) {
    // If a common header file contains dllexported function
    // declarations, many object files may end up with having the
    // same /EXPORT options. In order to save cost of parsing them,
    // we dedup them first.
    if (!DirectivesExports.insert(E).second)
      continue;

    Export Exp = parseExport(E);
    if (Config->Machine == I386 && Config->MinGW) {
      if (!isDecorated(Exp.Name))
        Exp.Name = Saver.save("_" + Exp.Name);
      if (!Exp.ExtName.empty() && !isDecorated(Exp.ExtName))
        Exp.ExtName = Saver.save("_" + Exp.ExtName);
    }
    Exp.Directives = true;
    Config->Exports.push_back(Exp);
  }

  for (auto *Arg : Args) {
    switch (Arg->getOption().getUnaliasedOption().getID()) {
    case OPT_aligncomm:
      parseAligncomm(Arg->getValue());
      break;
    case OPT_alternatename:
      parseAlternateName(Arg->getValue());
      break;
    case OPT_defaultlib:
      if (Optional<StringRef> Path = findLib(Arg->getValue()))
        enqueuePath(*Path, false);
      break;
    case OPT_entry:
      Config->Entry = addUndefined(mangle(Arg->getValue()));
      break;
    case OPT_failifmismatch:
      checkFailIfMismatch(Arg->getValue(), File);
      break;
    case OPT_incl:
      addUndefined(Arg->getValue());
      break;
    case OPT_merge:
      parseMerge(Arg->getValue());
      break;
    case OPT_nodefaultlib:
      Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()));
      break;
    case OPT_section:
      parseSection(Arg->getValue());
      break;
    case OPT_subsystem:
      parseSubsystem(Arg->getValue(), &Config->Subsystem,
                     &Config->MajorOSVersion, &Config->MinorOSVersion);
      break;
    case OPT_editandcontinue:
    case OPT_fastfail:
    case OPT_guardsym:
    case OPT_natvis:
    case OPT_throwingnew:
      break;
    default:
      error(Arg->getSpelling() + " is not allowed in .drectve");
    }
  }
}

// Find file from search paths. You can omit ".obj", this function takes
// care of that. Note that the returned path is not guaranteed to exist.
StringRef LinkerDriver::doFindFile(StringRef Filename) {
  bool HasPathSep = (Filename.find_first_of("/\\") != StringRef::npos);
  if (HasPathSep)
    return Filename;
  bool HasExt = Filename.contains('.');
  for (StringRef Dir : SearchPaths) {
    SmallString<128> Path = Dir;
    sys::path::append(Path, Filename);
    if (sys::fs::exists(Path.str()))
      return Saver.save(Path.str());
    if (!HasExt) {
      Path.append(".obj");
      if (sys::fs::exists(Path.str()))
        return Saver.save(Path.str());
    }
  }
  return Filename;
}

static Optional<sys::fs::UniqueID> getUniqueID(StringRef Path) {
  sys::fs::UniqueID Ret;
  if (sys::fs::getUniqueID(Path, Ret))
    return None;
  return Ret;
}

// Resolves a file path. This never returns the same path
// (in that case, it returns None).
Optional<StringRef> LinkerDriver::findFile(StringRef Filename) {
  StringRef Path = doFindFile(Filename);

  if (Optional<sys::fs::UniqueID> ID = getUniqueID(Path)) {
    bool Seen = !VisitedFiles.insert(*ID).second;
    if (Seen)
      return None;
  }

  if (Path.endswith_lower(".lib"))
    VisitedLibs.insert(sys::path::filename(Path));
  return Path;
}

// MinGW specific. If an embedded directive specified to link to
// foo.lib, but it isn't found, try libfoo.a instead.
StringRef LinkerDriver::doFindLibMinGW(StringRef Filename) {
  if (Filename.contains('/') || Filename.contains('\\'))
    return Filename;

  SmallString<128> S = Filename;
  sys::path::replace_extension(S, ".a");
  StringRef LibName = Saver.save("lib" + S.str());
  return doFindFile(LibName);
}

// Find library file from search path.
StringRef LinkerDriver::doFindLib(StringRef Filename) {
  // Add ".lib" to Filename if that has no file extension.
  bool HasExt = Filename.contains('.');
  if (!HasExt)
    Filename = Saver.save(Filename + ".lib");
  StringRef Ret = doFindFile(Filename);
  // For MinGW, if the find above didn't turn up anything, try
  // looking for a MinGW formatted library name.
  if (Config->MinGW && Ret == Filename)
    return doFindLibMinGW(Filename);
  return Ret;
}

// Resolves a library path. /nodefaultlib options are taken into
// consideration. This never returns the same path (in that case,
// it returns None).
Optional<StringRef> LinkerDriver::findLib(StringRef Filename) {
  if (Config->NoDefaultLibAll)
    return None;
  if (!VisitedLibs.insert(Filename.lower()).second)
    return None;

  StringRef Path = doFindLib(Filename);
  if (Config->NoDefaultLibs.count(Path))
    return None;

  if (Optional<sys::fs::UniqueID> ID = getUniqueID(Path))
    if (!VisitedFiles.insert(*ID).second)
      return None;
  return Path;
}

// Parses LIB environment which contains a list of search paths.
void LinkerDriver::addLibSearchPaths() {
  Optional<std::string> EnvOpt = Process::GetEnv("LIB");
  if (!EnvOpt.hasValue())
    return;
  StringRef Env = Saver.save(*EnvOpt);
  while (!Env.empty()) {
    StringRef Path;
    std::tie(Path, Env) = Env.split(';');
    SearchPaths.push_back(Path);
  }
}

Symbol *LinkerDriver::addUndefined(StringRef Name) {
  Symbol *B = Symtab->addUndefined(Name);
  if (!B->IsGCRoot) {
    B->IsGCRoot = true;
    Config->GCRoot.push_back(B);
  }
  return B;
}

StringRef LinkerDriver::mangleMaybe(Symbol *S) {
  // If the plain symbol name has already been resolved, do nothing.
  Undefined *Unmangled = dyn_cast<Undefined>(S);
  if (!Unmangled)
    return "";

  // Otherwise, see if a similar, mangled symbol exists in the symbol table.
  Symbol *Mangled = Symtab->findMangle(Unmangled->getName());
  if (!Mangled)
    return "";

  // If we find a similar mangled symbol, make this an alias to it and return
  // its name.
  log(Unmangled->getName() + " aliased to " + Mangled->getName());
  Unmangled->WeakAlias = Symtab->addUndefined(Mangled->getName());
  return Mangled->getName();
}

// Windows specific -- find default entry point name.
//
// There are four different entry point functions for Windows executables,
// each of which corresponds to a user-defined "main" function. This function
// infers an entry point from a user-defined "main" function.
StringRef LinkerDriver::findDefaultEntry() {
  assert(Config->Subsystem != IMAGE_SUBSYSTEM_UNKNOWN &&
         "must handle /subsystem before calling this");

  if (Config->MinGW)
    return mangle(Config->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI
                      ? "WinMainCRTStartup"
                      : "mainCRTStartup");

  if (Config->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) {
    if (findUnderscoreMangle("wWinMain")) {
      if (!findUnderscoreMangle("WinMain"))
        return mangle("wWinMainCRTStartup");
      warn("found both wWinMain and WinMain; using latter");
    }
    return mangle("WinMainCRTStartup");
  }
  if (findUnderscoreMangle("wmain")) {
    if (!findUnderscoreMangle("main"))
      return mangle("wmainCRTStartup");
    warn("found both wmain and main; using latter");
  }
  return mangle("mainCRTStartup");
}

WindowsSubsystem LinkerDriver::inferSubsystem() {
  if (Config->DLL)
    return IMAGE_SUBSYSTEM_WINDOWS_GUI;
  if (Config->MinGW)
    return IMAGE_SUBSYSTEM_WINDOWS_CUI;
  // Note that link.exe infers the subsystem from the presence of these
  // functions even if /entry: or /nodefaultlib are passed which causes them
  // to not be called.
  bool HaveMain = findUnderscoreMangle("main");
  bool HaveWMain = findUnderscoreMangle("wmain");
  bool HaveWinMain = findUnderscoreMangle("WinMain");
  bool HaveWWinMain = findUnderscoreMangle("wWinMain");
  if (HaveMain || HaveWMain) {
    if (HaveWinMain || HaveWWinMain) {
      warn(std::string("found ") + (HaveMain ? "main" : "wmain") + " and " +
           (HaveWinMain ? "WinMain" : "wWinMain") +
           "; defaulting to /subsystem:console");
    }
    return IMAGE_SUBSYSTEM_WINDOWS_CUI;
  }
  if (HaveWinMain || HaveWWinMain)
    return IMAGE_SUBSYSTEM_WINDOWS_GUI;
  return IMAGE_SUBSYSTEM_UNKNOWN;
}

static uint64_t getDefaultImageBase() {
  if (Config->is64())
    return Config->DLL ? 0x180000000 : 0x140000000;
  return Config->DLL ? 0x10000000 : 0x400000;
}

static std::string createResponseFile(const opt::InputArgList &Args,
                                      ArrayRef<StringRef> FilePaths,
                                      ArrayRef<StringRef> SearchPaths) {
  SmallString<0> Data;
  raw_svector_ostream OS(Data);

  for (auto *Arg : Args) {
    switch (Arg->getOption().getID()) {
    case OPT_linkrepro:
    case OPT_INPUT:
    case OPT_defaultlib:
    case OPT_libpath:
    case OPT_manifest:
    case OPT_manifest_colon:
    case OPT_manifestdependency:
    case OPT_manifestfile:
    case OPT_manifestinput:
    case OPT_manifestuac:
      break;
    case OPT_implib:
    case OPT_pdb:
    case OPT_out:
      OS << Arg->getSpelling() << sys::path::filename(Arg->getValue()) << "\n";
      break;
    default:
      OS << toString(*Arg) << "\n";
    }
  }

  for (StringRef Path : SearchPaths) {
    std::string RelPath = relativeToRoot(Path);
    OS << "/libpath:" << quote(RelPath) << "\n";
  }

  for (StringRef Path : FilePaths)
    OS << quote(relativeToRoot(Path)) << "\n";

  return Data.str();
}

enum class DebugKind { Unknown, None, Full, FastLink, GHash, Dwarf, Symtab };

static DebugKind parseDebugKind(const opt::InputArgList &Args) {
  auto *A = Args.getLastArg(OPT_debug, OPT_debug_opt);
  if (!A)
    return DebugKind::None;
  if (A->getNumValues() == 0)
    return DebugKind::Full;

  DebugKind Debug = StringSwitch<DebugKind>(A->getValue())
                     .CaseLower("none", DebugKind::None)
                     .CaseLower("full", DebugKind::Full)
                     .CaseLower("fastlink", DebugKind::FastLink)
                     // LLD extensions
                     .CaseLower("ghash", DebugKind::GHash)
                     .CaseLower("dwarf", DebugKind::Dwarf)
                     .CaseLower("symtab", DebugKind::Symtab)
                     .Default(DebugKind::Unknown);

  if (Debug == DebugKind::FastLink) {
    warn("/debug:fastlink unsupported; using /debug:full");
    return DebugKind::Full;
  }
  if (Debug == DebugKind::Unknown) {
    error("/debug: unknown option: " + Twine(A->getValue()));
    return DebugKind::None;
  }
  return Debug;
}

static unsigned parseDebugTypes(const opt::InputArgList &Args) {
  unsigned DebugTypes = static_cast<unsigned>(DebugType::None);

  if (auto *A = Args.getLastArg(OPT_debugtype)) {
    SmallVector<StringRef, 3> Types;
    A->getSpelling().split(Types, ',', /*KeepEmpty=*/false);

    for (StringRef Type : Types) {
      unsigned V = StringSwitch<unsigned>(Type.lower())
                       .Case("cv", static_cast<unsigned>(DebugType::CV))
                       .Case("pdata", static_cast<unsigned>(DebugType::PData))
                       .Case("fixup", static_cast<unsigned>(DebugType::Fixup))
                       .Default(0);
      if (V == 0) {
        warn("/debugtype: unknown option: " + Twine(A->getValue()));
        continue;
      }
      DebugTypes |= V;
    }
    return DebugTypes;
  }

  // Default debug types
  DebugTypes = static_cast<unsigned>(DebugType::CV);
  if (Args.hasArg(OPT_driver))
    DebugTypes |= static_cast<unsigned>(DebugType::PData);
  if (Args.hasArg(OPT_profile))
    DebugTypes |= static_cast<unsigned>(DebugType::Fixup);

  return DebugTypes;
}

static std::string getMapFile(const opt::InputArgList &Args) {
  auto *Arg = Args.getLastArg(OPT_lldmap, OPT_lldmap_file);
  if (!Arg)
    return "";
  if (Arg->getOption().getID() == OPT_lldmap_file)
    return Arg->getValue();

  assert(Arg->getOption().getID() == OPT_lldmap);
  StringRef OutFile = Config->OutputFile;
  return (OutFile.substr(0, OutFile.rfind('.')) + ".map").str();
}

static std::string getImplibPath() {
  if (!Config->Implib.empty())
    return Config->Implib;
  SmallString<128> Out = StringRef(Config->OutputFile);
  sys::path::replace_extension(Out, ".lib");
  return Out.str();
}

//
// The import name is caculated as the following:
//
//        | LIBRARY w/ ext |   LIBRARY w/o ext   | no LIBRARY
//   -----+----------------+---------------------+------------------
//   LINK | {value}        | {value}.{.dll/.exe} | {output name}
//    LIB | {value}        | {value}.dll         | {output name}.dll
//
static std::string getImportName(bool AsLib) {
  SmallString<128> Out;

  if (Config->ImportName.empty()) {
    Out.assign(sys::path::filename(Config->OutputFile));
    if (AsLib)
      sys::path::replace_extension(Out, ".dll");
  } else {
    Out.assign(Config->ImportName);
    if (!sys::path::has_extension(Out))
      sys::path::replace_extension(Out,
                                   (Config->DLL || AsLib) ? ".dll" : ".exe");
  }

  return Out.str();
}

static void createImportLibrary(bool AsLib) {
  std::vector<COFFShortExport> Exports;
  for (Export &E1 : Config->Exports) {
    COFFShortExport E2;
    E2.Name = E1.Name;
    E2.SymbolName = E1.SymbolName;
    E2.ExtName = E1.ExtName;
    E2.Ordinal = E1.Ordinal;
    E2.Noname = E1.Noname;
    E2.Data = E1.Data;
    E2.Private = E1.Private;
    E2.Constant = E1.Constant;
    Exports.push_back(E2);
  }

  auto HandleError = [](Error &&E) {
    handleAllErrors(std::move(E),
                    [](ErrorInfoBase &EIB) { error(EIB.message()); });
  };
  std::string LibName = getImportName(AsLib);
  std::string Path = getImplibPath();

  if (!Config->Incremental) {
    HandleError(writeImportLibrary(LibName, Path, Exports, Config->Machine,
                                   Config->MinGW));
    return;
  }

  // If the import library already exists, replace it only if the contents
  // have changed.
  ErrorOr<std::unique_ptr<MemoryBuffer>> OldBuf = MemoryBuffer::getFile(
      Path, /*FileSize*/ -1, /*RequiresNullTerminator*/ false);
  if (!OldBuf) {
    HandleError(writeImportLibrary(LibName, Path, Exports, Config->Machine,
                                   Config->MinGW));
    return;
  }

  SmallString<128> TmpName;
  if (std::error_code EC =
          sys::fs::createUniqueFile(Path + ".tmp-%%%%%%%%.lib", TmpName))
    fatal("cannot create temporary file for import library " + Path + ": " +
          EC.message());

  if (Error E = writeImportLibrary(LibName, TmpName, Exports, Config->Machine,
                                   Config->MinGW)) {
    HandleError(std::move(E));
    return;
  }

  std::unique_ptr<MemoryBuffer> NewBuf = check(MemoryBuffer::getFile(
      TmpName, /*FileSize*/ -1, /*RequiresNullTerminator*/ false));
  if ((*OldBuf)->getBuffer() != NewBuf->getBuffer()) {
    OldBuf->reset();
    HandleError(errorCodeToError(sys::fs::rename(TmpName, Path)));
  } else {
    sys::fs::remove(TmpName);
  }
}

static void parseModuleDefs(StringRef Path) {
  std::unique_ptr<MemoryBuffer> MB = CHECK(
      MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path);
  COFFModuleDefinition M = check(parseCOFFModuleDefinition(
      MB->getMemBufferRef(), Config->Machine, Config->MinGW));

  if (Config->OutputFile.empty())
    Config->OutputFile = Saver.save(M.OutputFile);
  Config->ImportName = Saver.save(M.ImportName);
  if (M.ImageBase)
    Config->ImageBase = M.ImageBase;
  if (M.StackReserve)
    Config->StackReserve = M.StackReserve;
  if (M.StackCommit)
    Config->StackCommit = M.StackCommit;
  if (M.HeapReserve)
    Config->HeapReserve = M.HeapReserve;
  if (M.HeapCommit)
    Config->HeapCommit = M.HeapCommit;
  if (M.MajorImageVersion)
    Config->MajorImageVersion = M.MajorImageVersion;
  if (M.MinorImageVersion)
    Config->MinorImageVersion = M.MinorImageVersion;
  if (M.MajorOSVersion)
    Config->MajorOSVersion = M.MajorOSVersion;
  if (M.MinorOSVersion)
    Config->MinorOSVersion = M.MinorOSVersion;

  for (COFFShortExport E1 : M.Exports) {
    Export E2;
    // In simple cases, only Name is set. Renamed exports are parsed
    // and set as "ExtName = Name". If Name has the form "OtherDll.Func",
    // it shouldn't be a normal exported function but a forward to another
    // DLL instead. This is supported by both MS and GNU linkers.
    if (E1.ExtName != E1.Name && StringRef(E1.Name).contains('.')) {
      E2.Name = Saver.save(E1.ExtName);
      E2.ForwardTo = Saver.save(E1.Name);
      Config->Exports.push_back(E2);
      continue;
    }
    E2.Name = Saver.save(E1.Name);
    E2.ExtName = Saver.save(E1.ExtName);
    E2.Ordinal = E1.Ordinal;
    E2.Noname = E1.Noname;
    E2.Data = E1.Data;
    E2.Private = E1.Private;
    E2.Constant = E1.Constant;
    Config->Exports.push_back(E2);
  }
}

void LinkerDriver::enqueueTask(std::function<void()> Task) {
  TaskQueue.push_back(std::move(Task));
}

bool LinkerDriver::run() {
  ScopedTimer T(InputFileTimer);

  bool DidWork = !TaskQueue.empty();
  while (!TaskQueue.empty()) {
    TaskQueue.front()();
    TaskQueue.pop_front();
  }
  return DidWork;
}

// Parse an /order file. If an option is given, the linker places
// COMDAT sections in the same order as their names appear in the
// given file.
static void parseOrderFile(StringRef Arg) {
  // For some reason, the MSVC linker requires a filename to be
  // preceded by "@".
  if (!Arg.startswith("@")) {
    error("malformed /order option: '@' missing");
    return;
  }

  // Get a list of all comdat sections for error checking.
  DenseSet<StringRef> Set;
  for (Chunk *C : Symtab->getChunks())
    if (auto *Sec = dyn_cast<SectionChunk>(C))
      if (Sec->Sym)
        Set.insert(Sec->Sym->getName());

  // Open a file.
  StringRef Path = Arg.substr(1);
  std::unique_ptr<MemoryBuffer> MB = CHECK(
      MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path);

  // Parse a file. An order file contains one symbol per line.
  // All symbols that were not present in a given order file are
  // considered to have the lowest priority 0 and are placed at
  // end of an output section.
  for (std::string S : args::getLines(MB->getMemBufferRef())) {
    if (Config->Machine == I386 && !isDecorated(S))
      S = "_" + S;

    if (Set.count(S) == 0) {
      if (Config->WarnMissingOrderSymbol)
        warn("/order:" + Arg + ": missing symbol: " + S + " [LNK4037]");
    }
    else
      Config->Order[S] = INT_MIN + Config->Order.size();
  }
}

static void markAddrsig(Symbol *S) {
  if (auto *D = dyn_cast_or_null<Defined>(S))
    if (SectionChunk *C = dyn_cast_or_null<SectionChunk>(D->getChunk()))
      C->KeepUnique = true;
}

static void findKeepUniqueSections() {
  // Exported symbols could be address-significant in other executables or DSOs,
  // so we conservatively mark them as address-significant.
  for (Export &R : Config->Exports)
    markAddrsig(R.Sym);

  // Visit the address-significance table in each object file and mark each
  // referenced symbol as address-significant.
  for (ObjFile *Obj : ObjFile::Instances) {
    ArrayRef<Symbol *> Syms = Obj->getSymbols();
    if (Obj->AddrsigSec) {
      ArrayRef<uint8_t> Contents;
      cantFail(
          Obj->getCOFFObj()->getSectionContents(Obj->AddrsigSec, Contents));
      const uint8_t *Cur = Contents.begin();
      while (Cur != Contents.end()) {
        unsigned Size;
        const char *Err;
        uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err);
        if (Err)
          fatal(toString(Obj) + ": could not decode addrsig section: " + Err);
        if (SymIndex >= Syms.size())
          fatal(toString(Obj) + ": invalid symbol index in addrsig section");
        markAddrsig(Syms[SymIndex]);
        Cur += Size;
      }
    } else {
      // If an object file does not have an address-significance table,
      // conservatively mark all of its symbols as address-significant.
      for (Symbol *S : Syms)
        markAddrsig(S);
    }
  }
}

// link.exe replaces each %foo% in AltPath with the contents of environment
// variable foo, and adds the two magic env vars _PDB (expands to the basename
// of pdb's output path) and _EXT (expands to the extension of the output
// binary).
// lld only supports %_PDB% and %_EXT% and warns on references to all other env
// vars.
static void parsePDBAltPath(StringRef AltPath) {
  SmallString<128> Buf;
  StringRef PDBBasename =
      sys::path::filename(Config->PDBPath, sys::path::Style::windows);
  StringRef BinaryExtension =
      sys::path::extension(Config->OutputFile, sys::path::Style::windows);
  if (!BinaryExtension.empty())
    BinaryExtension = BinaryExtension.substr(1); // %_EXT% does not include '.'.

  // Invariant:
  //   +--------- Cursor ('a...' might be the empty string).
  //   |   +----- FirstMark
  //   |   |   +- SecondMark
  //   v   v   v
  //   a...%...%...
  size_t Cursor = 0;
  while (Cursor < AltPath.size()) {
    size_t FirstMark, SecondMark;
    if ((FirstMark = AltPath.find('%', Cursor)) == StringRef::npos ||
        (SecondMark = AltPath.find('%', FirstMark + 1)) == StringRef::npos) {
      // Didn't find another full fragment, treat rest of string as literal.
      Buf.append(AltPath.substr(Cursor));
      break;
    }

    // Found a full fragment. Append text in front of first %, and interpret
    // text between first and second % as variable name.
    Buf.append(AltPath.substr(Cursor, FirstMark - Cursor));
    StringRef Var = AltPath.substr(FirstMark, SecondMark - FirstMark + 1);
    if (Var.equals_lower("%_pdb%"))
      Buf.append(PDBBasename);
    else if (Var.equals_lower("%_ext%"))
      Buf.append(BinaryExtension);
    else {
      warn("only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping " +
           Var + " as literal");
      Buf.append(Var);
    }

    Cursor = SecondMark + 1;
  }

  Config->PDBAltPath = Buf;
}

/// Check that at most one resource obj file was used.
/// Call after ObjFile::Instances is complete.
static void diagnoseMultipleResourceObjFiles() {
  // The .rsrc$01 section in a resource obj file contains a tree description
  // of resources.  Merging multiple resource obj files would require merging
  // the trees instead of using usual linker section merging semantics.
  // Since link.exe disallows linking more than one resource obj file with
  // LNK4078, mirror that.  The normal use of resource files is to give the
  // linker many .res files, which are then converted to a single resource obj
  // file internally, so this is not a big restriction in practice.
  ObjFile *ResourceObjFile = nullptr;
  for (ObjFile *F : ObjFile::Instances) {
    if (!F->IsResourceObjFile)
      continue;

    if (!ResourceObjFile) {
      ResourceObjFile = F;
      continue;
    }

    error(toString(F) +
          ": more than one resource obj file not allowed, already got " +
          toString(ResourceObjFile));
  }
}

// In MinGW, if no symbols are chosen to be exported, then all symbols are
// automatically exported by default. This behavior can be forced by the
// -export-all-symbols option, so that it happens even when exports are
// explicitly specified. The automatic behavior can be disabled using the
// -exclude-all-symbols option, so that lld-link behaves like link.exe rather
// than MinGW in the case that nothing is explicitly exported.
void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &Args) {
  if (!Config->DLL)
    return;

  if (!Args.hasArg(OPT_export_all_symbols)) {
    if (!Config->Exports.empty())
      return;
    if (Args.hasArg(OPT_exclude_all_symbols))
      return;
  }

  AutoExporter Exporter;

  for (auto *Arg : Args.filtered(OPT_wholearchive_file))
    if (Optional<StringRef> Path = doFindFile(Arg->getValue()))
      Exporter.addWholeArchive(*Path);

  Symtab->forEachSymbol([&](Symbol *S) {
    auto *Def = dyn_cast<Defined>(S);
    if (!Exporter.shouldExport(Def))
      return;

    Export E;
    E.Name = Def->getName();
    E.Sym = Def;
    if (Chunk *C = Def->getChunk())
      if (!(C->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
        E.Data = true;
    Config->Exports.push_back(E);
  });
}

void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
  // Needed for LTO.
  InitializeAllTargetInfos();
  InitializeAllTargets();
  InitializeAllTargetMCs();
  InitializeAllAsmParsers();
  InitializeAllAsmPrinters();

  // If the first command line argument is "/lib", link.exe acts like lib.exe.
  // We call our own implementation of lib.exe that understands bitcode files.
  if (ArgsArr.size() > 1 && StringRef(ArgsArr[1]).equals_lower("/lib")) {
    if (llvm::libDriverMain(ArgsArr.slice(1)) != 0)
      fatal("lib failed");
    return;
  }

  // Parse command line options.
  ArgParser Parser;
  opt::InputArgList Args = Parser.parseLINK(ArgsArr);

  // Parse and evaluate -mllvm options.
  std::vector<const char *> V;
  V.push_back("lld-link (LLVM option parsing)");
  for (auto *Arg : Args.filtered(OPT_mllvm))
    V.push_back(Arg->getValue());
  cl::ParseCommandLineOptions(V.size(), V.data());

  // Handle /errorlimit early, because error() depends on it.
  if (auto *Arg = Args.getLastArg(OPT_errorlimit)) {
    int N = 20;
    StringRef S = Arg->getValue();
    if (S.getAsInteger(10, N))
      error(Arg->getSpelling() + " number expected, but got " + S);
    errorHandler().ErrorLimit = N;
  }

  // Handle /help
  if (Args.hasArg(OPT_help)) {
    printHelp(ArgsArr[0]);
    return;
  }

  lld::ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_threads_no, true);

  if (Args.hasArg(OPT_show_timing))
    Config->ShowTiming = true;

  Config->ShowSummary = Args.hasArg(OPT_summary);

  ScopedTimer T(Timer::root());
  // Handle --version, which is an lld extension. This option is a bit odd
  // because it doesn't start with "/", but we deliberately chose "--" to
  // avoid conflict with /version and for compatibility with clang-cl.
  if (Args.hasArg(OPT_dash_dash_version)) {
    outs() << getLLDVersion() << "\n";
    return;
  }

  // Handle /lldmingw early, since it can potentially affect how other
  // options are handled.
  Config->MinGW = Args.hasArg(OPT_lldmingw);

  if (auto *Arg = Args.getLastArg(OPT_linkrepro)) {
    SmallString<64> Path = StringRef(Arg->getValue());
    sys::path::append(Path, "repro.tar");

    Expected<std::unique_ptr<TarWriter>> ErrOrWriter =
        TarWriter::create(Path, "repro");

    if (ErrOrWriter) {
      Tar = std::move(*ErrOrWriter);
    } else {
      error("/linkrepro: failed to open " + Path + ": " +
            toString(ErrOrWriter.takeError()));
    }
  }

  if (!Args.hasArg(OPT_INPUT)) {
    if (Args.hasArg(OPT_deffile))
      Config->NoEntry = true;
    else
      fatal("no input files");
  }

  // Construct search path list.
  SearchPaths.push_back("");
  for (auto *Arg : Args.filtered(OPT_libpath))
    SearchPaths.push_back(Arg->getValue());
  addLibSearchPaths();

  // Handle /ignore
  for (auto *Arg : Args.filtered(OPT_ignore)) {
    SmallVector<StringRef, 8> Vec;
    StringRef(Arg->getValue()).split(Vec, ',');
    for (StringRef S : Vec) {
      if (S == "4037")
        Config->WarnMissingOrderSymbol = false;
      else if (S == "4099")
        Config->WarnDebugInfoUnusable = false;
      else if (S == "4217")
        Config->WarnLocallyDefinedImported = false;
      // Other warning numbers are ignored.
    }
  }

  // Handle /out
  if (auto *Arg = Args.getLastArg(OPT_out))
    Config->OutputFile = Arg->getValue();

  // Handle /verbose
  if (Args.hasArg(OPT_verbose))
    Config->Verbose = true;
  errorHandler().Verbose = Config->Verbose;

  // Handle /force or /force:unresolved
  if (Args.hasArg(OPT_force, OPT_force_unresolved))
    Config->ForceUnresolved = true;

  // Handle /force or /force:multiple
  if (Args.hasArg(OPT_force, OPT_force_multiple))
    Config->ForceMultiple = true;

  // Handle /force or /force:multipleres
  if (Args.hasArg(OPT_force, OPT_force_multipleres))
    Config->ForceMultipleRes = true;

  // Handle /debug
  DebugKind Debug = parseDebugKind(Args);
  if (Debug == DebugKind::Full || Debug == DebugKind::Dwarf ||
      Debug == DebugKind::GHash) {
    Config->Debug = true;
    Config->Incremental = true;
  }

  // Handle /demangle
  Config->Demangle = Args.hasFlag(OPT_demangle, OPT_demangle_no);

  // Handle /debugtype
  Config->DebugTypes = parseDebugTypes(Args);

  // Handle /pdb
  bool ShouldCreatePDB =
      (Debug == DebugKind::Full || Debug == DebugKind::GHash);
  if (ShouldCreatePDB) {
    if (auto *Arg = Args.getLastArg(OPT_pdb))
      Config->PDBPath = Arg->getValue();
    if (auto *Arg = Args.getLastArg(OPT_pdbaltpath))
      Config->PDBAltPath = Arg->getValue();
    if (Args.hasArg(OPT_natvis))
      Config->NatvisFiles = Args.getAllArgValues(OPT_natvis);

    if (auto *Arg = Args.getLastArg(OPT_pdb_source_path))
      Config->PDBSourcePath = Arg->getValue();
  }

  // Handle /noentry
  if (Args.hasArg(OPT_noentry)) {
    if (Args.hasArg(OPT_dll))
      Config->NoEntry = true;
    else
      error("/noentry must be specified with /dll");
  }

  // Handle /dll
  if (Args.hasArg(OPT_dll)) {
    Config->DLL = true;
    Config->ManifestID = 2;
  }

  // Handle /dynamicbase and /fixed. We can't use hasFlag for /dynamicbase
  // because we need to explicitly check whether that option or its inverse was
  // present in the argument list in order to handle /fixed.
  auto *DynamicBaseArg = Args.getLastArg(OPT_dynamicbase, OPT_dynamicbase_no);
  if (DynamicBaseArg &&
      DynamicBaseArg->getOption().getID() == OPT_dynamicbase_no)
    Config->DynamicBase = false;

  // MSDN claims "/FIXED:NO is the default setting for a DLL, and /FIXED is the
  // default setting for any other project type.", but link.exe defaults to
  // /FIXED:NO for exe outputs as well. Match behavior, not docs.
  bool Fixed = Args.hasFlag(OPT_fixed, OPT_fixed_no, false);
  if (Fixed) {
    if (DynamicBaseArg &&
        DynamicBaseArg->getOption().getID() == OPT_dynamicbase) {
      error("/fixed must not be specified with /dynamicbase");
    } else {
      Config->Relocatable = false;
      Config->DynamicBase = false;
    }
  }

  // Handle /appcontainer
  Config->AppContainer =
      Args.hasFlag(OPT_appcontainer, OPT_appcontainer_no, false);

  // Handle /machine
  if (auto *Arg = Args.getLastArg(OPT_machine)) {
    Config->Machine = getMachineType(Arg->getValue());
    if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN)
      fatal(Twine("unknown /machine argument: ") + Arg->getValue());
  }

  // Handle /nodefaultlib:<filename>
  for (auto *Arg : Args.filtered(OPT_nodefaultlib))
    Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()));

  // Handle /nodefaultlib
  if (Args.hasArg(OPT_nodefaultlib_all))
    Config->NoDefaultLibAll = true;

  // Handle /base
  if (auto *Arg = Args.getLastArg(OPT_base))
    parseNumbers(Arg->getValue(), &Config->ImageBase);

  // Handle /filealign
  if (auto *Arg = Args.getLastArg(OPT_filealign)) {
    parseNumbers(Arg->getValue(), &Config->FileAlign);
    if (!isPowerOf2_64(Config->FileAlign))
      error("/filealign: not a power of two: " + Twine(Config->FileAlign));
  }

  // Handle /stack
  if (auto *Arg = Args.getLastArg(OPT_stack))
    parseNumbers(Arg->getValue(), &Config->StackReserve, &Config->StackCommit);

  // Handle /guard:cf
  if (auto *Arg = Args.getLastArg(OPT_guard))
    parseGuard(Arg->getValue());

  // Handle /heap
  if (auto *Arg = Args.getLastArg(OPT_heap))
    parseNumbers(Arg->getValue(), &Config->HeapReserve, &Config->HeapCommit);

  // Handle /version
  if (auto *Arg = Args.getLastArg(OPT_version))
    parseVersion(Arg->getValue(), &Config->MajorImageVersion,
                 &Config->MinorImageVersion);

  // Handle /subsystem
  if (auto *Arg = Args.getLastArg(OPT_subsystem))
    parseSubsystem(Arg->getValue(), &Config->Subsystem, &Config->MajorOSVersion,
                   &Config->MinorOSVersion);

  // Handle /timestamp
  if (llvm::opt::Arg *Arg = Args.getLastArg(OPT_timestamp, OPT_repro)) {
    if (Arg->getOption().getID() == OPT_repro) {
      Config->Timestamp = 0;
      Config->Repro = true;
    } else {
      Config->Repro = false;
      StringRef Value(Arg->getValue());
      if (Value.getAsInteger(0, Config->Timestamp))
        fatal(Twine("invalid timestamp: ") + Value +
              ".  Expected 32-bit integer");
    }
  } else {
    Config->Repro = false;
    Config->Timestamp = time(nullptr);
  }

  // Handle /alternatename
  for (auto *Arg : Args.filtered(OPT_alternatename))
    parseAlternateName(Arg->getValue());

  // Handle /include
  for (auto *Arg : Args.filtered(OPT_incl))
    addUndefined(Arg->getValue());

  // Handle /implib
  if (auto *Arg = Args.getLastArg(OPT_implib))
    Config->Implib = Arg->getValue();

  // Handle /opt.
  bool DoGC = Debug == DebugKind::None || Args.hasArg(OPT_profile);
  unsigned ICFLevel =
      Args.hasArg(OPT_profile) ? 0 : 1; // 0: off, 1: limited, 2: on
  unsigned TailMerge = 1;
  for (auto *Arg : Args.filtered(OPT_opt)) {
    std::string Str = StringRef(Arg->getValue()).lower();
    SmallVector<StringRef, 1> Vec;
    StringRef(Str).split(Vec, ',');
    for (StringRef S : Vec) {
      if (S == "ref") {
        DoGC = true;
      } else if (S == "noref") {
        DoGC = false;
      } else if (S == "icf" || S.startswith("icf=")) {
        ICFLevel = 2;
      } else if (S == "noicf") {
        ICFLevel = 0;
      } else if (S == "lldtailmerge") {
        TailMerge = 2;
      } else if (S == "nolldtailmerge") {
        TailMerge = 0;
      } else if (S.startswith("lldlto=")) {
        StringRef OptLevel = S.substr(7);
        if (OptLevel.getAsInteger(10, Config->LTOO) || Config->LTOO > 3)
          error("/opt:lldlto: invalid optimization level: " + OptLevel);
      } else if (S.startswith("lldltojobs=")) {
        StringRef Jobs = S.substr(11);
        if (Jobs.getAsInteger(10, Config->ThinLTOJobs) ||
            Config->ThinLTOJobs == 0)
          error("/opt:lldltojobs: invalid job count: " + Jobs);
      } else if (S.startswith("lldltopartitions=")) {
        StringRef N = S.substr(17);
        if (N.getAsInteger(10, Config->LTOPartitions) ||
            Config->LTOPartitions == 0)
          error("/opt:lldltopartitions: invalid partition count: " + N);
      } else if (S != "lbr" && S != "nolbr")
        error("/opt: unknown option: " + S);
    }
  }

  // Limited ICF is enabled if GC is enabled and ICF was never mentioned
  // explicitly.
  // FIXME: LLD only implements "limited" ICF, i.e. it only merges identical
  // code. If the user passes /OPT:ICF explicitly, LLD should merge identical
  // comdat readonly data.
  if (ICFLevel == 1 && !DoGC)
    ICFLevel = 0;
  Config->DoGC = DoGC;
  Config->DoICF = ICFLevel > 0;
  Config->TailMerge = (TailMerge == 1 && Config->DoICF) || TailMerge == 2;

  // Handle /lldsavetemps
  if (Args.hasArg(OPT_lldsavetemps))
    Config->SaveTemps = true;

  // Handle /kill-at
  if (Args.hasArg(OPT_kill_at))
    Config->KillAt = true;

  // Handle /lldltocache
  if (auto *Arg = Args.getLastArg(OPT_lldltocache))
    Config->LTOCache = Arg->getValue();

  // Handle /lldsavecachepolicy
  if (auto *Arg = Args.getLastArg(OPT_lldltocachepolicy))
    Config->LTOCachePolicy = CHECK(
        parseCachePruningPolicy(Arg->getValue()),
        Twine("/lldltocachepolicy: invalid cache policy: ") + Arg->getValue());

  // Handle /failifmismatch
  for (auto *Arg : Args.filtered(OPT_failifmismatch))
    checkFailIfMismatch(Arg->getValue(), nullptr);

  // Handle /merge
  for (auto *Arg : Args.filtered(OPT_merge))
    parseMerge(Arg->getValue());

  // Add default section merging rules after user rules. User rules take
  // precedence, but we will emit a warning if there is a conflict.
  parseMerge(".idata=.rdata");
  parseMerge(".didat=.rdata");
  parseMerge(".edata=.rdata");
  parseMerge(".xdata=.rdata");
  parseMerge(".bss=.data");

  if (Config->MinGW) {
    parseMerge(".ctors=.rdata");
    parseMerge(".dtors=.rdata");
    parseMerge(".CRT=.rdata");
  }

  // Handle /section
  for (auto *Arg : Args.filtered(OPT_section))
    parseSection(Arg->getValue());

  // Handle /aligncomm
  for (auto *Arg : Args.filtered(OPT_aligncomm))
    parseAligncomm(Arg->getValue());

  // Handle /manifestdependency. This enables /manifest unless /manifest:no is
  // also passed.
  if (auto *Arg = Args.getLastArg(OPT_manifestdependency)) {
    Config->ManifestDependency = Arg->getValue();
    Config->Manifest = Configuration::SideBySide;
  }

  // Handle /manifest and /manifest:
  if (auto *Arg = Args.getLastArg(OPT_manifest, OPT_manifest_colon)) {
    if (Arg->getOption().getID() == OPT_manifest)
      Config->Manifest = Configuration::SideBySide;
    else
      parseManifest(Arg->getValue());
  }

  // Handle /manifestuac
  if (auto *Arg = Args.getLastArg(OPT_manifestuac))
    parseManifestUAC(Arg->getValue());

  // Handle /manifestfile
  if (auto *Arg = Args.getLastArg(OPT_manifestfile))
    Config->ManifestFile = Arg->getValue();

  // Handle /manifestinput
  for (auto *Arg : Args.filtered(OPT_manifestinput))
    Config->ManifestInput.push_back(Arg->getValue());

  if (!Config->ManifestInput.empty() &&
      Config->Manifest != Configuration::Embed) {
    fatal("/manifestinput: requires /manifest:embed");
  }

  // Handle miscellaneous boolean flags.
  Config->AllowBind = Args.hasFlag(OPT_allowbind, OPT_allowbind_no, true);
  Config->AllowIsolation =
      Args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true);
  Config->Incremental =
      Args.hasFlag(OPT_incremental, OPT_incremental_no,
                   !Config->DoGC && !Config->DoICF && !Args.hasArg(OPT_order) &&
                       !Args.hasArg(OPT_profile));
  Config->IntegrityCheck =
      Args.hasFlag(OPT_integritycheck, OPT_integritycheck_no, false);
  Config->NxCompat = Args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true);
  for (auto *Arg : Args.filtered(OPT_swaprun))
    parseSwaprun(Arg->getValue());
  Config->TerminalServerAware =
      !Config->DLL && Args.hasFlag(OPT_tsaware, OPT_tsaware_no, true);
  Config->DebugDwarf = Debug == DebugKind::Dwarf;
  Config->DebugGHashes = Debug == DebugKind::GHash;
  Config->DebugSymtab = Debug == DebugKind::Symtab;

  Config->MapFile = getMapFile(Args);

  if (Config->Incremental && Args.hasArg(OPT_profile)) {
    warn("ignoring '/incremental' due to '/profile' specification");
    Config->Incremental = false;
  }

  if (Config->Incremental && Args.hasArg(OPT_order)) {
    warn("ignoring '/incremental' due to '/order' specification");
    Config->Incremental = false;
  }

  if (Config->Incremental && Config->DoGC) {
    warn("ignoring '/incremental' because REF is enabled; use '/opt:noref' to "
         "disable");
    Config->Incremental = false;
  }

  if (Config->Incremental && Config->DoICF) {
    warn("ignoring '/incremental' because ICF is enabled; use '/opt:noicf' to "
         "disable");
    Config->Incremental = false;
  }

  if (errorCount())
    return;

  std::set<sys::fs::UniqueID> WholeArchives;
  for (auto *Arg : Args.filtered(OPT_wholearchive_file))
    if (Optional<StringRef> Path = doFindFile(Arg->getValue()))
      if (Optional<sys::fs::UniqueID> ID = getUniqueID(*Path))
        WholeArchives.insert(*ID);

  // A predicate returning true if a given path is an argument for
  // /wholearchive:, or /wholearchive is enabled globally.
  // This function is a bit tricky because "foo.obj /wholearchive:././foo.obj"
  // needs to be handled as "/wholearchive:foo.obj foo.obj".
  auto IsWholeArchive = [&](StringRef Path) -> bool {
    if (Args.hasArg(OPT_wholearchive_flag))
      return true;
    if (Optional<sys::fs::UniqueID> ID = getUniqueID(Path))
      return WholeArchives.count(*ID);
    return false;
  };

  // Create a list of input files. Files can be given as arguments
  // for /defaultlib option.
  for (auto *Arg : Args.filtered(OPT_INPUT, OPT_wholearchive_file))
    if (Optional<StringRef> Path = findFile(Arg->getValue()))
      enqueuePath(*Path, IsWholeArchive(*Path));

  for (auto *Arg : Args.filtered(OPT_defaultlib))
    if (Optional<StringRef> Path = findLib(Arg->getValue()))
      enqueuePath(*Path, false);

  // Windows specific -- Create a resource file containing a manifest file.
  if (Config->Manifest == Configuration::Embed)
    addBuffer(createManifestRes(), false);

  // Read all input files given via the command line.
  run();

  if (errorCount())
    return;

  // We should have inferred a machine type by now from the input files, but if
  // not we assume x64.
  if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
    warn("/machine is not specified. x64 is assumed");
    Config->Machine = AMD64;
  }
  Config->Wordsize = Config->is64() ? 8 : 4;

  // Handle /functionpadmin
  for (auto *Arg : Args.filtered(OPT_functionpadmin, OPT_functionpadmin_opt))
    parseFunctionPadMin(Arg, Config->Machine);

  // Input files can be Windows resource files (.res files). We use
  // WindowsResource to convert resource files to a regular COFF file,
  // then link the resulting file normally.
  if (!Resources.empty())
    Symtab->addFile(make<ObjFile>(convertResToCOFF(Resources)));

  if (Tar)
    Tar->append("response.txt",
                createResponseFile(Args, FilePaths,
                                   ArrayRef<StringRef>(SearchPaths).slice(1)));

  // Handle /largeaddressaware
  Config->LargeAddressAware = Args.hasFlag(
      OPT_largeaddressaware, OPT_largeaddressaware_no, Config->is64());

  // Handle /highentropyva
  Config->HighEntropyVA =
      Config->is64() &&
      Args.hasFlag(OPT_highentropyva, OPT_highentropyva_no, true);

  if (!Config->DynamicBase &&
      (Config->Machine == ARMNT || Config->Machine == ARM64))
    error("/dynamicbase:no is not compatible with " +
          machineToStr(Config->Machine));

  // Handle /export
  for (auto *Arg : Args.filtered(OPT_export)) {
    Export E = parseExport(Arg->getValue());
    if (Config->Machine == I386) {
      if (!isDecorated(E.Name))
        E.Name = Saver.save("_" + E.Name);
      if (!E.ExtName.empty() && !isDecorated(E.ExtName))
        E.ExtName = Saver.save("_" + E.ExtName);
    }
    Config->Exports.push_back(E);
  }

  // Handle /def
  if (auto *Arg = Args.getLastArg(OPT_deffile)) {
    // parseModuleDefs mutates Config object.
    parseModuleDefs(Arg->getValue());
  }

  // Handle generation of import library from a def file.
  if (!Args.hasArg(OPT_INPUT)) {
    fixupExports();
    createImportLibrary(/*AsLib=*/true);
    return;
  }

  // Windows specific -- if no /subsystem is given, we need to infer
  // that from entry point name.  Must happen before /entry handling,
  // and after the early return when just writing an import library.
  if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
    Config->Subsystem = inferSubsystem();
    if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN)
      fatal("subsystem must be defined");
  }

  // Handle /entry and /dll
  if (auto *Arg = Args.getLastArg(OPT_entry)) {
    Config->Entry = addUndefined(mangle(Arg->getValue()));
  } else if (!Config->Entry && !Config->NoEntry) {
    if (Args.hasArg(OPT_dll)) {
      StringRef S = (Config->Machine == I386) ? "__DllMainCRTStartup@12"
                                              : "_DllMainCRTStartup";
      Config->Entry = addUndefined(S);
    } else {
      // Windows specific -- If entry point name is not given, we need to
      // infer that from user-defined entry name.
      StringRef S = findDefaultEntry();
      if (S.empty())
        fatal("entry point must be defined");
      Config->Entry = addUndefined(S);
      log("Entry name inferred: " + S);
    }
  }

  // Handle /delayload
  for (auto *Arg : Args.filtered(OPT_delayload)) {
    Config->DelayLoads.insert(StringRef(Arg->getValue()).lower());
    if (Config->Machine == I386) {
      Config->DelayLoadHelper = addUndefined("___delayLoadHelper2@8");
    } else {
      Config->DelayLoadHelper = addUndefined("__delayLoadHelper2");
    }
  }

  // Set default image name if neither /out or /def set it.
  if (Config->OutputFile.empty()) {
    Config->OutputFile =
        getOutputPath((*Args.filtered(OPT_INPUT).begin())->getValue());
  }

  // Fail early if an output file is not writable.
  if (auto E = tryCreateFile(Config->OutputFile)) {
    error("cannot open output file " + Config->OutputFile + ": " + E.message());
    return;
  }

  if (ShouldCreatePDB) {
    // Put the PDB next to the image if no /pdb flag was passed.
    if (Config->PDBPath.empty()) {
      Config->PDBPath = Config->OutputFile;
      sys::path::replace_extension(Config->PDBPath, ".pdb");
    }

    // The embedded PDB path should be the absolute path to the PDB if no
    // /pdbaltpath flag was passed.
    if (Config->PDBAltPath.empty()) {
      Config->PDBAltPath = Config->PDBPath;

      // It's important to make the path absolute and remove dots.  This path
      // will eventually be written into the PE header, and certain Microsoft
      // tools won't work correctly if these assumptions are not held.
      sys::fs::make_absolute(Config->PDBAltPath);
      sys::path::remove_dots(Config->PDBAltPath);
    } else {
      // Don't do this earlier, so that Config->OutputFile is ready.
      parsePDBAltPath(Config->PDBAltPath);
    }
  }

  // Set default image base if /base is not given.
  if (Config->ImageBase == uint64_t(-1))
    Config->ImageBase = getDefaultImageBase();

  Symtab->addSynthetic(mangle("__ImageBase"), nullptr);
  if (Config->Machine == I386) {
    Symtab->addAbsolute("___safe_se_handler_table", 0);
    Symtab->addAbsolute("___safe_se_handler_count", 0);
  }

  Symtab->addAbsolute(mangle("__guard_fids_count"), 0);
  Symtab->addAbsolute(mangle("__guard_fids_table"), 0);
  Symtab->addAbsolute(mangle("__guard_flags"), 0);
  Symtab->addAbsolute(mangle("__guard_iat_count"), 0);
  Symtab->addAbsolute(mangle("__guard_iat_table"), 0);
  Symtab->addAbsolute(mangle("__guard_longjmp_count"), 0);
  Symtab->addAbsolute(mangle("__guard_longjmp_table"), 0);
  // Needed for MSVC 2017 15.5 CRT.
  Symtab->addAbsolute(mangle("__enclave_config"), 0);

  if (Config->MinGW) {
    Symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0);
    Symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0);
    Symtab->addAbsolute(mangle("__CTOR_LIST__"), 0);
    Symtab->addAbsolute(mangle("__DTOR_LIST__"), 0);
  }

  // This code may add new undefined symbols to the link, which may enqueue more
  // symbol resolution tasks, so we need to continue executing tasks until we
  // converge.
  do {
    // Windows specific -- if entry point is not found,
    // search for its mangled names.
    if (Config->Entry)
      mangleMaybe(Config->Entry);

    // Windows specific -- Make sure we resolve all dllexported symbols.
    for (Export &E : Config->Exports) {
      if (!E.ForwardTo.empty())
        continue;
      E.Sym = addUndefined(E.Name);
      if (!E.Directives)
        E.SymbolName = mangleMaybe(E.Sym);
    }

    // Add weak aliases. Weak aliases is a mechanism to give remaining
    // undefined symbols final chance to be resolved successfully.
    for (auto Pair : Config->AlternateNames) {
      StringRef From = Pair.first;
      StringRef To = Pair.second;
      Symbol *Sym = Symtab->find(From);
      if (!Sym)
        continue;
      if (auto *U = dyn_cast<Undefined>(Sym))
        if (!U->WeakAlias)
          U->WeakAlias = Symtab->addUndefined(To);
    }

    // Windows specific -- if __load_config_used can be resolved, resolve it.
    if (Symtab->findUnderscore("_load_config_used"))
      addUndefined(mangle("_load_config_used"));
  } while (run());

  if (errorCount())
    return;

  // Do LTO by compiling bitcode input files to a set of native COFF files then
  // link those files.
  Symtab->addCombinedLTOObjects();
  run();

  if (Args.hasArg(OPT_include_optional)) {
    // Handle /includeoptional
    for (auto *Arg : Args.filtered(OPT_include_optional))
      if (dyn_cast_or_null<Lazy>(Symtab->find(Arg->getValue())))
        addUndefined(Arg->getValue());
    while (run());
  }

  if (Config->MinGW) {
    // Load any further object files that might be needed for doing automatic
    // imports.
    //
    // For cases with no automatically imported symbols, this iterates once
    // over the symbol table and doesn't do anything.
    //
    // For the normal case with a few automatically imported symbols, this
    // should only need to be run once, since each new object file imported
    // is an import library and wouldn't add any new undefined references,
    // but there's nothing stopping the __imp_ symbols from coming from a
    // normal object file as well (although that won't be used for the
    // actual autoimport later on). If this pass adds new undefined references,
    // we won't iterate further to resolve them.
    Symtab->loadMinGWAutomaticImports();
    run();
  }

  // Make sure we have resolved all symbols.
  Symtab->reportRemainingUndefines();
  if (errorCount())
    return;

  // Handle /safeseh.
  if (Args.hasFlag(OPT_safeseh, OPT_safeseh_no, false)) {
    for (ObjFile *File : ObjFile::Instances)
      if (!File->hasSafeSEH())
        error("/safeseh: " + File->getName() + " is not compatible with SEH");
    if (errorCount())
      return;
  }

  if (Config->MinGW) {
    // In MinGW, all symbols are automatically exported if no symbols
    // are chosen to be exported.
    maybeExportMinGWSymbols(Args);

    // Make sure the crtend.o object is the last object file. This object
    // file can contain terminating section chunks that need to be placed
    // last. GNU ld processes files and static libraries explicitly in the
    // order provided on the command line, while lld will pull in needed
    // files from static libraries only after the last object file on the
    // command line.
    for (auto I = ObjFile::Instances.begin(), E = ObjFile::Instances.end();
         I != E; I++) {
      ObjFile *File = *I;
      if (isCrtend(File->getName())) {
        ObjFile::Instances.erase(I);
        ObjFile::Instances.push_back(File);
        break;
      }
    }
  }

  // Windows specific -- when we are creating a .dll file, we also
  // need to create a .lib file.
  if (!Config->Exports.empty() || Config->DLL) {
    fixupExports();
    createImportLibrary(/*AsLib=*/false);
    assignExportOrdinals();
  }

  // Handle /output-def (MinGW specific).
  if (auto *Arg = Args.getLastArg(OPT_output_def))
    writeDefFile(Arg->getValue());

  // Set extra alignment for .comm symbols
  for (auto Pair : Config->AlignComm) {
    StringRef Name = Pair.first;
    uint32_t Alignment = Pair.second;

    Symbol *Sym = Symtab->find(Name);
    if (!Sym) {
      warn("/aligncomm symbol " + Name + " not found");
      continue;
    }

    // If the symbol isn't common, it must have been replaced with a regular
    // symbol, which will carry its own alignment.
    auto *DC = dyn_cast<DefinedCommon>(Sym);
    if (!DC)
      continue;

    CommonChunk *C = DC->getChunk();
    C->setAlignment(std::max(C->getAlignment(), Alignment));
  }

  // Windows specific -- Create a side-by-side manifest file.
  if (Config->Manifest == Configuration::SideBySide)
    createSideBySideManifest();

  // Handle /order. We want to do this at this moment because we
  // need a complete list of comdat sections to warn on nonexistent
  // functions.
  if (auto *Arg = Args.getLastArg(OPT_order))
    parseOrderFile(Arg->getValue());

  // Identify unreferenced COMDAT sections.
  if (Config->DoGC)
    markLive(Symtab->getChunks());

  // Needs to happen after the last call to addFile().
  diagnoseMultipleResourceObjFiles();

  // Identify identical COMDAT sections to merge them.
  if (Config->DoICF) {
    findKeepUniqueSections();
    doICF(Symtab->getChunks());
  }

  // Write the result.
  writeResult();

  // Stop early so we can print the results.
  Timer::root().stop();
  if (Config->ShowTiming)
    Timer::root().print();
}

} // namespace coff
} // namespace lld
