//===- 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 "DebugTypes.h"
#include "Driver.h"
#include "Config.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/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;
}

// 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());

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