//===--- Driver.cpp - Swift compiler driver -------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file contains implementations of parts of the compiler driver.
//
//===----------------------------------------------------------------------===//

#include "swift/Driver/Driver.h"

#include "ToolChains.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsDriver.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/OutputFileMap.h"
#include "swift/Basic/Platform.h"
#include "swift/Basic/Range.h"
#include "swift/Basic/Statistic.h"
#include "swift/Basic/TaskQueue.h"
#include "swift/Basic/Version.h"
#include "swift/Config.h"
#include "swift/Driver/Action.h"
#include "swift/Driver/Compilation.h"
#include "swift/Driver/Job.h"
#include "swift/Driver/PrettyStackTrace.h"
#include "swift/Driver/ToolChain.h"
#include "swift/Option/Options.h"
#include "swift/Option/SanitizerOptions.h"
#include "swift/Parse/Lexer.h"
#include "swift/Strings.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Config/config.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Remarks/RemarkFormat.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"

#include "CompilationRecord.h"

#include <memory>

using namespace swift;
using namespace swift::driver;
using namespace llvm::opt;

Driver::Driver(StringRef DriverExecutable,
               StringRef Name,
               ArrayRef<const char *> Args,
               DiagnosticEngine &Diags)
  : Opts(createSwiftOptTable()), Diags(Diags),
    Name(Name), DriverExecutable(DriverExecutable),
    DefaultTargetTriple(llvm::sys::getDefaultTargetTriple()) {
      
  // The driver kind must be parsed prior to parsing arguments, since that
  // affects how arguments are parsed.
  parseDriverKind(Args.slice(1));
}

Driver::~Driver() = default;

void Driver::parseDriverKind(ArrayRef<const char *> Args) {
  // The default driver kind is determined by Name.
  StringRef DriverName = Name;

  std::string OptName;
  // However, the driver kind may be overridden if the first argument is
  // --driver-mode.
  if (!Args.empty()) {
    OptName = getOpts().getOption(options::OPT_driver_mode).getPrefixedName();

    StringRef FirstArg(Args[0]);
    if (FirstArg.startswith(OptName))
      DriverName = FirstArg.drop_front(OptName.size());
  }

  Optional<DriverKind> Kind =
  llvm::StringSwitch<Optional<DriverKind>>(DriverName)
  .Case("swift", DriverKind::Interactive)
  .Case("swiftc", DriverKind::Batch)
  .Case("swift-autolink-extract", DriverKind::AutolinkExtract)
  .Case("swift-indent", DriverKind::SwiftIndent)
  .Case("swift-symbolgraph-extract", DriverKind::SymbolGraph)
  .Default(None);
  
  if (Kind.hasValue())
    driverKind = Kind.getValue();
  else if (!OptName.empty())
    Diags.diagnose({}, diag::error_invalid_arg_value, OptName, DriverName);
}

ArrayRef<const char *> Driver::getArgsWithoutProgramNameAndDriverMode(
                                      ArrayRef<const char *> Args) const {
  Args = Args.slice(1);
  if (Args.empty())
    return Args;

  const std::string OptName =
    getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
  if (StringRef(Args[0]).startswith(OptName))
    Args = Args.slice(1);
  return Args;
}

static void validateBridgingHeaderArgs(DiagnosticEngine &diags,
                                       const ArgList &args) {
  if (!args.hasArgNoClaim(options::OPT_import_objc_header))
    return;

  if (args.hasArgNoClaim(options::OPT_import_underlying_module))
    diags.diagnose({}, diag::error_framework_bridging_header);

  if (args.hasArgNoClaim(options::OPT_emit_module_interface,
                         options::OPT_emit_module_interface_path)) {
    diags.diagnose({}, diag::error_bridging_header_module_interface);
  }
}

static void validateWarningControlArgs(DiagnosticEngine &diags,
                                       const ArgList &args) {
  if (args.hasArg(options::OPT_suppress_warnings) &&
      args.hasFlag(options::OPT_warnings_as_errors,
                   options::OPT_no_warnings_as_errors, false)) {
    diags.diagnose(SourceLoc(), diag::error_conflicting_options,
                   "-warnings-as-errors", "-suppress-warnings");
  }
}

static void validateProfilingArgs(DiagnosticEngine &diags,
                                  const ArgList &args) {
  const Arg *ProfileGenerate = args.getLastArg(options::OPT_profile_generate);
  const Arg *ProfileUse = args.getLastArg(options::OPT_profile_use);
  if (ProfileGenerate && ProfileUse) {
    diags.diagnose(SourceLoc(), diag::error_conflicting_options,
                   "-profile-generate", "-profile-use");
  }

  // Check if the profdata is missing
  if (ProfileUse && !llvm::sys::fs::exists(ProfileUse->getValue())) {
    diags.diagnose(SourceLoc(), diag::error_profile_missing,
                   ProfileUse->getValue());
  }
}

static void validateDependencyScanningArgs(DiagnosticEngine &diags,
                                           const ArgList &args) {
  const Arg *ExternalDependencyMap = args.getLastArg(options::OPT_placeholder_dependency_module_map);
  const Arg *ScanDependencies = args.getLastArg(options::OPT_scan_dependencies);
  const Arg *Prescan = args.getLastArg(options::OPT_import_prescan);
  if (ExternalDependencyMap && !ScanDependencies) {
    diags.diagnose(SourceLoc(), diag::error_requirement_not_met,
                   "-placeholder-dependency-module-map-file", "-scan-dependencies");
  }
  if (Prescan && !ScanDependencies) {
    diags.diagnose(SourceLoc(), diag::error_requirement_not_met,
                   "-import-prescan", "-scan-dependencies");
  }
}

static void validateDebugInfoArgs(DiagnosticEngine &diags,
                                  const ArgList &args) {
  // Check for missing debug option when verifying debug info.
  if (args.hasArg(options::OPT_verify_debug_info)) {
    Arg *debugOpt = args.getLastArg(swift::options::OPT_g_Group);
    if (!debugOpt || debugOpt->getOption().matches(swift::options::OPT_gnone)) {
      diags.diagnose(SourceLoc(),
                     diag::verify_debug_info_requires_debug_option);
    }
  }

  // Check for any -debug-prefix-map options that aren't of the form
  // 'original=remapped' (either side can be empty, however).
  for (auto A : args.getAllArgValues(options::OPT_debug_prefix_map))
    if (A.find('=') == StringRef::npos)
      diags.diagnose(SourceLoc(), diag::error_invalid_debug_prefix_map, A);

  // Check for any -coverage-prefix-map options that aren't of the form
  // 'original=remapped' (either side can be empty, however).
  for (auto A : args.getAllArgValues(options::OPT_coverage_prefix_map))
    if (A.find('=') == StringRef::npos)
      diags.diagnose(SourceLoc(), diag::error_invalid_coverage_prefix_map, A);
}

static void validateVerifyIncrementalDependencyArgs(DiagnosticEngine &diags,
                                                    const ArgList &args) {
  // No option? No problem!
  if (!args.hasArg(options::OPT_verify_incremental_dependencies)) {
    return;
  }

  // Make sure we see -incremental but not -wmo, no matter in what order they're
  // in - the build systems can pass them both and just hope the last one wins.
  if (args.hasArg(options::OPT_incremental) &&
      !args.hasArg(options::OPT_whole_module_optimization)) {
    return;
  }

  diags.diagnose(SourceLoc(),
                 diag::verify_incremental_dependencies_needs_incremental);
}

static void validateCompilationConditionArgs(DiagnosticEngine &diags,
                                             const ArgList &args) {
  for (const Arg *A : args.filtered(options::OPT_D)) {
    StringRef name = A->getValue();
    if (name.find('=') != StringRef::npos) {
      diags.diagnose(SourceLoc(),
                     diag::cannot_assign_value_to_conditional_compilation_flag,
                     name);
    } else if (name.startswith("-D")) {
      diags.diagnose(SourceLoc(), diag::redundant_prefix_compilation_flag,
                     name);
    } else if (!Lexer::isIdentifier(name)) {
      diags.diagnose(SourceLoc(), diag::invalid_conditional_compilation_flag,
                     name);
    }
  }
}

static void validateSearchPathArgs(DiagnosticEngine &diags,
                                   const ArgList &args) {
  for (const Arg *A : args.filtered(options::OPT_F, options::OPT_Fsystem)) {
    StringRef name = A->getValue();
    if (name.endswith(".framework") || name.endswith(".framework/"))
      diags.diagnose(SourceLoc(),
                     diag::framework_search_path_includes_framework_extension,
                     name);
  }
}

static void validateAutolinkingArgs(DiagnosticEngine &diags,
                                    const ArgList &args,
                                    const llvm::Triple &T) {
  auto *forceLoadArg = args.getLastArg(options::OPT_autolink_force_load);
  if (!forceLoadArg)
    return;
  auto *incrementalArg = args.getLastArg(options::OPT_incremental);
  if (!incrementalArg)
    return;

  if (T.supportsCOMDAT())
    return;

  // Note: -incremental can itself be overridden by other arguments later
  // on, but since -autolink-force-load is a rare and not-really-recommended
  // option it's not worth modeling that complexity here (or moving the
  // check somewhere else).
  diags.diagnose(SourceLoc(), diag::error_option_not_supported,
                 forceLoadArg->getSpelling(), incrementalArg->getSpelling());
}

/// Perform miscellaneous early validation of arguments.
static void validateArgs(DiagnosticEngine &diags, const ArgList &args,
                         const llvm::Triple &T) {
  validateBridgingHeaderArgs(diags, args);
  validateWarningControlArgs(diags, args);
  validateProfilingArgs(diags, args);
  validateDependencyScanningArgs(diags, args);
  validateDebugInfoArgs(diags, args);
  validateCompilationConditionArgs(diags, args);
  validateSearchPathArgs(diags, args);
  validateAutolinkingArgs(diags, args, T);
  validateVerifyIncrementalDependencyArgs(diags, args);
}

std::unique_ptr<ToolChain>
Driver::buildToolChain(const llvm::opt::InputArgList &ArgList) {

  if (const Arg *A = ArgList.getLastArg(options::OPT_target)) {
    DefaultTargetTriple = llvm::Triple::normalize(A->getValue());
  }

  llvm::Triple target(DefaultTargetTriple);

  // Backward compatibility hack: infer "simulator" environment for x86
  // iOS/tvOS/watchOS.
  if (tripleInfersSimulatorEnvironment(target)) {
    // Set the simulator environment.
    target.setEnvironment(llvm::Triple::EnvironmentType::Simulator);

    auto newTargetTriple = target.normalize();
    Diags.diagnose(SourceLoc(), diag::warning_inferred_simulator_target,
                   DefaultTargetTriple, newTargetTriple);

    DefaultTargetTriple = newTargetTriple;
  }

  switch (target.getOS()) {
  case llvm::Triple::IOS:
  case llvm::Triple::TvOS:
  case llvm::Triple::WatchOS:
  case llvm::Triple::Darwin:
  case llvm::Triple::MacOSX: {
    Optional<llvm::Triple> targetVariant;
    if (const Arg *A = ArgList.getLastArg(options::OPT_target_variant))
      targetVariant = llvm::Triple(llvm::Triple::normalize(A->getValue()));

    return std::make_unique<toolchains::Darwin>(*this, target, targetVariant);
  }
  case llvm::Triple::Linux:
    if (target.isAndroid())
      return std::make_unique<toolchains::Android>(*this, target);
    return std::make_unique<toolchains::GenericUnix>(*this, target);
  case llvm::Triple::FreeBSD:
    return std::make_unique<toolchains::GenericUnix>(*this, target);
  case llvm::Triple::OpenBSD:
    return std::make_unique<toolchains::OpenBSD>(*this, target);
  case llvm::Triple::Win32:
    if (target.isWindowsCygwinEnvironment())
      return std::make_unique<toolchains::Cygwin>(*this, target);
    return std::make_unique<toolchains::Windows>(*this, target);
  case llvm::Triple::Haiku:
    return std::make_unique<toolchains::GenericUnix>(*this, target);
  case llvm::Triple::WASI:
    return std::make_unique<toolchains::GenericUnix>(*this, target);
  default:
    Diags.diagnose(SourceLoc(), diag::error_unknown_target,
                   ArgList.getLastArg(options::OPT_target)->getValue());
    break;
  }
  return nullptr;
}

std::unique_ptr<sys::TaskQueue> Driver::buildTaskQueue(const Compilation &C) {
  const auto &ArgList = C.getArgs();
  unsigned NumberOfParallelCommands = 1;
  if (const Arg *A = ArgList.getLastArg(options::OPT_j)) {
    if (StringRef(A->getValue()).getAsInteger(10, NumberOfParallelCommands)) {
      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
                     A->getAsString(ArgList), A->getValue());
      return nullptr;
    }
  }
  if (environmentVariableRequestedMaximumDeterminism()) {
      NumberOfParallelCommands = 1;
      Diags.diagnose(SourceLoc(), diag::remark_max_determinism_overriding,
                     "-j");
  }

  const bool DriverSkipExecution =
    ArgList.hasArg(options::OPT_driver_skip_execution,
                   options::OPT_driver_print_jobs);
  if (DriverSkipExecution) {
    return std::make_unique<sys::DummyTaskQueue>(NumberOfParallelCommands);
  } else {
    return std::make_unique<sys::TaskQueue>(NumberOfParallelCommands,
                                             C.getStatsReporter());
  }
}

static void computeArgsHash(SmallString<32> &out, const DerivedArgList &args) {
  SmallVector<const Arg *, 32> interestingArgs;
  interestingArgs.reserve(args.size());
  std::copy_if(args.begin(), args.end(), std::back_inserter(interestingArgs),
               [](const Arg *arg) {
    return !arg->getOption().hasFlag(options::DoesNotAffectIncrementalBuild) &&
           arg->getOption().getKind() != Option::InputClass;
  });

  llvm::array_pod_sort(interestingArgs.begin(), interestingArgs.end(),
                       [](const Arg * const *lhs, const Arg * const *rhs)->int {
    auto cmpID = (*lhs)->getOption().getID() - (*rhs)->getOption().getID();
    if (cmpID != 0)
      return cmpID;
    return (*lhs)->getIndex() - (*rhs)->getIndex();
  });

  llvm::MD5 hash;
  for (const Arg *arg : interestingArgs) {
    hash.update(arg->getOption().getID());
    for (const char *value : const_cast<Arg *>(arg)->getValues())
      hash.update(value);
  }

  llvm::MD5::MD5Result hashBuf;
  hash.final(hashBuf);
  llvm::MD5::stringifyResult(hashBuf, out);
}

class Driver::InputInfoMap
    : public llvm::SmallDenseMap<const Arg *, CompileJobAction::InputInfo, 16> {
};
using InputInfoMap = Driver::InputInfoMap;

/// Get the filename for build record. Returns true if failed.
static bool getCompilationRecordPath(std::string &buildRecordPath,
                                     const OutputInfo &OI,
                                     const Optional<OutputFileMap> &OFM,
                                     DiagnosticEngine *Diags) {
  if (!OFM) {
    // FIXME: This should work without an output file map. We should have
    // another way to specify a build record and where to put intermediates.
    if (Diags)
      Diags->diagnose(SourceLoc(), diag::incremental_requires_output_file_map);
    return true;
  }

  if (auto *masterOutputMap = OFM->getOutputMapForSingleOutput())
    buildRecordPath = masterOutputMap->lookup(file_types::TY_SwiftDeps);

  if (buildRecordPath.empty()) {
    if (Diags)
      Diags->diagnose(SourceLoc(),
                      diag::incremental_requires_build_record_entry,
                      file_types::getTypeName(file_types::TY_SwiftDeps));
    return true;
  }

  return false;
}

static std::string failedToReadOutOfDateMap(bool ShowIncrementalBuildDecisions,
                                          StringRef buildRecordPath,
                                          StringRef reason = "") {
  std::string why = "malformed build record file";
  if (!reason.empty()) {
    why += " ";
    why += reason;
  }
  if (ShowIncrementalBuildDecisions) {
    llvm::outs() << "Incremental compilation has been disabled due to " << why
                 << " '" << buildRecordPath << "'.\n";
  }
  return why;
}

static SmallVector<StringRef, 8> findRemovedInputs(
    const InputFileList &inputs,
    const llvm::StringMap<CompileJobAction::InputInfo> &previousInputs);

static void dealWithRemovedInputs(ArrayRef<StringRef> removedInputs,
                                  bool ShowIncrementalBuildDecisions);

/// Returns why ignore incrementality
static std::string
populateOutOfDateMap(InputInfoMap &map, llvm::sys::TimePoint<> &LastBuildTime,
                     StringRef argsHashStr, const InputFileList &inputs,
                     StringRef buildRecordPath,
                     const bool EnableSourceRangeDependencies,
                     const bool ShowIncrementalBuildDecisions) {
  // Treat a missing file as "no previous build".
  auto buffer = llvm::MemoryBuffer::getFile(buildRecordPath);
  if (!buffer) {
    if (ShowIncrementalBuildDecisions)
      llvm::outs() << "Incremental compilation could not read build record.\n";
    return "could not read build record";
  }

  namespace yaml = llvm::yaml;
  using InputInfo = CompileJobAction::InputInfo;

  llvm::SourceMgr SM;
  yaml::Stream stream(buffer.get()->getMemBufferRef(), SM);

  auto I = stream.begin();
  if (I == stream.end() || !I->getRoot())
    return failedToReadOutOfDateMap(ShowIncrementalBuildDecisions,
                                    buildRecordPath);

  auto *topLevelMap = dyn_cast<yaml::MappingNode>(I->getRoot());
  if (!topLevelMap)
    return failedToReadOutOfDateMap(ShowIncrementalBuildDecisions,
                                    buildRecordPath);
  SmallString<64> scratch;

  llvm::StringMap<InputInfo> previousInputs;
  bool versionValid = false;
  bool optionsMatch = true;

  auto readTimeValue = [&scratch](yaml::Node *node,
                                  llvm::sys::TimePoint<> &timeValue) -> bool {
    auto *seq = dyn_cast<yaml::SequenceNode>(node);
    if (!seq)
      return true;

    auto seqI = seq->begin(), seqE = seq->end();
    if (seqI == seqE)
      return true;

    auto *secondsRaw = dyn_cast<yaml::ScalarNode>(&*seqI);
    if (!secondsRaw)
      return true;
    std::time_t parsedSeconds;
    if (secondsRaw->getValue(scratch).getAsInteger(10, parsedSeconds))
      return true;

    ++seqI;
    if (seqI == seqE)
      return true;

    auto *nanosecondsRaw = dyn_cast<yaml::ScalarNode>(&*seqI);
    if (!nanosecondsRaw)
      return true;
    std::chrono::system_clock::rep parsedNanoseconds;
    if (nanosecondsRaw->getValue(scratch).getAsInteger(10, parsedNanoseconds))
      return true;

    ++seqI;
    if (seqI != seqE)
      return true;

    timeValue = llvm::sys::TimePoint<>(std::chrono::seconds(parsedSeconds));
    timeValue += std::chrono::nanoseconds(parsedNanoseconds);
    return false;
  };

  // FIXME: LLVM's YAML support does incremental parsing in such a way that
  // for-range loops break.
  SmallString<64> CompilationRecordSwiftVersion;
  for (auto i = topLevelMap->begin(), e = topLevelMap->end(); i != e; ++i) {
    auto *key = cast<yaml::ScalarNode>(i->getKey());
    StringRef keyStr = key->getValue(scratch);

    using compilation_record::TopLevelKey;
    if (keyStr == compilation_record::getName(TopLevelKey::Version)) {
      auto *value = dyn_cast<yaml::ScalarNode>(i->getValue());
      if (!value) {
        auto reason = ("Malformed value for key '" + keyStr + "'.")
          .toStringRef(scratch);
        return failedToReadOutOfDateMap(ShowIncrementalBuildDecisions,
                                        buildRecordPath, reason);
      }

      // NB: We check against
      // swift::version::Version::getCurrentLanguageVersion() here because any
      // -swift-version argument is handled in the argsHashStr check that
      // follows.
      CompilationRecordSwiftVersion = value->getValue(scratch);
      versionValid = (CompilationRecordSwiftVersion
                      == version::getSwiftFullVersion(
                        version::Version::getCurrentLanguageVersion()));

    } else if (keyStr == compilation_record::getName(TopLevelKey::Options)) {
      auto *value = dyn_cast<yaml::ScalarNode>(i->getValue());
      if (!value)
        return "no name node in build record";
      optionsMatch = (argsHashStr == value->getValue(scratch));

    } else if (keyStr == compilation_record::getName(TopLevelKey::BuildTime)) {
      auto *value = dyn_cast<yaml::SequenceNode>(i->getValue());
      if (!value) {
        auto reason = ("Malformed value for key '" + keyStr + "'.")
          .toStringRef(scratch);
        return failedToReadOutOfDateMap(ShowIncrementalBuildDecisions,
                                        buildRecordPath, reason);
      }
      llvm::sys::TimePoint<> timeVal;
      if (readTimeValue(i->getValue(), timeVal))
        return "could not read time value in build record";
      LastBuildTime = timeVal;

    } else if (keyStr == compilation_record::getName(TopLevelKey::Inputs)) {
      auto *inputMap = dyn_cast<yaml::MappingNode>(i->getValue());
      if (!inputMap) {
        auto reason = ("Malformed value for key '" + keyStr + "'.")
          .toStringRef(scratch);
        return failedToReadOutOfDateMap(ShowIncrementalBuildDecisions,
                                        buildRecordPath, reason);
      }

      // FIXME: LLVM's YAML support does incremental parsing in such a way that
      // for-range loops break.
      for (auto i = inputMap->begin(), e = inputMap->end(); i != e; ++i) {
        auto *key = dyn_cast<yaml::ScalarNode>(i->getKey());
        if (!key)
          return "no input entry in build record";

        auto *value = dyn_cast<yaml::SequenceNode>(i->getValue());
        if (!value)
          return "no sequence node for input entry in build record";

        using compilation_record::getInfoStatusForIdentifier;
        auto previousBuildState =
          getInfoStatusForIdentifier(value->getRawTag());
        if (!previousBuildState)
          return "no previous build state in build record";

        llvm::sys::TimePoint<> timeValue;
        if (readTimeValue(value, timeValue))
          return "could not read time value in build record";

        auto inputName = key->getValue(scratch);
        previousInputs[inputName] = { *previousBuildState, timeValue };
      }
    }
  }

  if (!versionValid) {
    if (ShowIncrementalBuildDecisions) {
      auto v = version::getSwiftFullVersion(
          version::Version::getCurrentLanguageVersion());
      llvm::outs() << "Incremental compilation has been disabled, due to a "
                   << "compiler version mismatch.\n"
                   << "\tCompiling with: " << v << "\n"
                   << "\tPreviously compiled with: "
                   << CompilationRecordSwiftVersion << "\n";
    }
    return "compiler version mismatch";
  }

  if (!optionsMatch) {
    if (ShowIncrementalBuildDecisions) {
      llvm::outs() << "Incremental compilation has been disabled, because "
                   << "different arguments were passed to the compiler.\n";
    }
    return "different arguments passed to compiler";
  }

  unsigned numMatchingPreviouslyCompiledInputs = 0;
  for (auto &inputPair : inputs) {
    auto iter = previousInputs.find(inputPair.second->getValue());
    if (iter == previousInputs.end())
      map[inputPair.second] = CompileJobAction::InputInfo::makeNewlyAdded();
    else {
      map[inputPair.second] = iter->getValue();
      ++numMatchingPreviouslyCompiledInputs;
    }
  }
  assert(numMatchingPreviouslyCompiledInputs <= previousInputs.size());
  auto const wereAnyInputsRemoved =
      numMatchingPreviouslyCompiledInputs < previousInputs.size();
  if (!wereAnyInputsRemoved)
    return "";

  const auto removedInputs = findRemovedInputs(inputs, previousInputs);
  assert(!removedInputs.empty());

  dealWithRemovedInputs(removedInputs, ShowIncrementalBuildDecisions);
  return "an input was removed"; // recompile everything; could do better
                                 // someday
}

static SmallVector<StringRef, 8> findRemovedInputs(
    const InputFileList &inputs,
    const llvm::StringMap<CompileJobAction::InputInfo> &previousInputs) {
  llvm::DenseSet<StringRef> inputArgs;
  for (auto &inputPair : inputs) {
    inputArgs.insert(inputPair.second->getValue());
  }
  SmallVector<StringRef, 8> missingInputs;
  for (auto &previousInput : previousInputs) {
    auto previousInputArg = previousInput.getKey();
    if (inputArgs.find(previousInputArg) == inputArgs.end()) {
      missingInputs.push_back(previousInputArg);
    }
  }
  return missingInputs;
}

static void showRemovedInputs(ArrayRef<StringRef> removedInputs);

/// Return true if hadError
static void dealWithRemovedInputs(ArrayRef<StringRef> removedInputs,
                                  const bool ShowIncrementalBuildDecisions) {
  // If a file was removed, we've lost its dependency info. Rebuild everything.
  // FIXME: Can we do better?
  // Yes, for range-based recompilation.
  if (ShowIncrementalBuildDecisions)
    showRemovedInputs(removedInputs);
}

static void showRemovedInputs(ArrayRef<StringRef> removedInputs) {

  llvm::outs() << "Incremental compilation has been disabled, because "
               << "the following inputs were used in the previous "
               << "compilation, but not in the current compilation:\n";

  for (auto &missing : removedInputs)
    llvm::outs() << "\t" << missing << "\n";
}

// warn if -embed-bitcode is set and the output type is not an object
static void validateEmbedBitcode(DerivedArgList &Args, const OutputInfo &OI,
                                 DiagnosticEngine &Diags) {
  if (Args.hasArg(options::OPT_embed_bitcode) &&
      OI.CompilerOutputType != file_types::TY_Object) {
    Diags.diagnose(SourceLoc(), diag::warn_ignore_embed_bitcode);
    Args.eraseArg(options::OPT_embed_bitcode);
  }

  if (Args.hasArg(options::OPT_embed_bitcode_marker) &&
      OI.CompilerOutputType != file_types::TY_Object) {
    Diags.diagnose(SourceLoc(), diag::warn_ignore_embed_bitcode_marker);
    Args.eraseArg(options::OPT_embed_bitcode_marker);
  }
}

/// Gets the filelist threshold to use. Diagnoses and returns true on error.
static bool getFilelistThreshold(DerivedArgList &Args, size_t &FilelistThreshold,
                                   DiagnosticEngine &Diags) {
  FilelistThreshold = 128;

  // claim and diagnose deprecated -driver-use-filelists
  bool HasUseFilelists = Args.hasArg(options::OPT_driver_use_filelists);
  if (HasUseFilelists)
    Diags.diagnose(SourceLoc(), diag::warn_use_filelists_deprecated);

  if (const Arg *A = Args.getLastArg(options::OPT_driver_filelist_threshold)) {
    // Use the supplied threshold
    if (StringRef(A->getValue()).getAsInteger(10, FilelistThreshold)) {
      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
                     A->getAsString(Args), A->getValue());
      return true;
    }
  } else if (HasUseFilelists) {
    // Treat -driver-use-filelists as -driver-filelist-threshold=0
    FilelistThreshold = 0;
  } // else stick with the default

  return false;
}

static unsigned
getDriverBatchSeed(llvm::opt::InputArgList &ArgList,
                   DiagnosticEngine &Diags) {
  unsigned DriverBatchSeed = 0;
  if (const Arg *A = ArgList.getLastArg(options::OPT_driver_batch_seed)) {
    if (StringRef(A->getValue()).getAsInteger(10, DriverBatchSeed)) {
      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
                     A->getAsString(ArgList), A->getValue());
    }
  }
  return DriverBatchSeed;
}

static Optional<unsigned>
getDriverBatchCount(llvm::opt::InputArgList &ArgList,
                    DiagnosticEngine &Diags)
{
  if (const Arg *A = ArgList.getLastArg(options::OPT_driver_batch_count)) {
    unsigned Count = 0;
    if (StringRef(A->getValue()).getAsInteger(10, Count)) {
      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
                     A->getAsString(ArgList), A->getValue());
    } else {
      return Count;
    }
  }
  return None;
}

static bool computeIncremental(const llvm::opt::InputArgList *ArgList,
                               const bool ShowIncrementalBuildDecisions) {
  if (!ArgList->hasArg(options::OPT_incremental))
    return false;

  const char *ReasonToDisable =
      ArgList->hasFlag(options::OPT_whole_module_optimization,
                       options::OPT_no_whole_module_optimization,
                       false)
          ? "is not compatible with whole module optimization."
          : ArgList->hasArg(options::OPT_embed_bitcode)
                ? "is not currently compatible with embedding LLVM IR bitcode."
                : nullptr;

  if (!ReasonToDisable)
    return true;

  if (ShowIncrementalBuildDecisions) {
    llvm::outs() << "Incremental compilation has been disabled, because it "
                 << ReasonToDisable;
  }
  return false;
}

static std::string
computeWorkingDirectory(const llvm::opt::InputArgList *ArgList) {
  if (auto *A = ArgList->getLastArg(options::OPT_working_directory)) {
    SmallString<128> workingDirectory;
    workingDirectory = A->getValue();
    llvm::sys::fs::make_absolute(workingDirectory);
    std::string result = workingDirectory.str().str();
    return result;
  }
  return std::string();
}

static std::unique_ptr<UnifiedStatsReporter>
createStatsReporter(const llvm::opt::InputArgList *ArgList,
                    const InputFileList &Inputs, const OutputInfo OI,
                    StringRef DefaultTargetTriple) {
  const Arg *A = ArgList->getLastArgNoClaim(options::OPT_stats_output_dir);
  if (!A)
    return nullptr;

  StringRef OptType;
  if (const Arg *OptA = ArgList->getLastArgNoClaim(options::OPT_O_Group)) {
    OptType = OptA->getSpelling();
  }
  StringRef InputName;
  if (Inputs.size() == 1) {
    InputName = Inputs[0].second->getSpelling();
  }
  StringRef OutputType = file_types::getExtension(OI.CompilerOutputType);
  return std::make_unique<UnifiedStatsReporter>("swift-driver",
                                                 OI.ModuleName,
                                                 InputName,
                                                 DefaultTargetTriple,
                                                 OutputType,
                                                 OptType,
                                                 A->getValue());
}

static bool
computeContinueBuildingAfterErrors(const bool BatchMode,
                                   const llvm::opt::InputArgList *ArgList) {
  // Note: Batch mode handling of serialized diagnostics requires that all
  // batches get to run, in order to make sure that all diagnostics emitted
  // during the compilation end up in at least one serialized diagnostic file.
  // Therefore, treat batch mode as implying -continue-building-after-errors.
  // (This behavior could be limited to only when serialized diagnostics are
  // being emitted, but this seems more consistent and less surprising for
  // users.)
  // FIXME: We don't really need (or want) a full ContinueBuildingAfterErrors.
  // If we fail to precompile a bridging header, for example, there's no need
  // to go on to compilation of source files, and if compilation of source files
  // fails, we shouldn't try to link. Instead, we'd want to let all jobs finish
  // but not schedule any new ones.
  return BatchMode ||
         ArgList->hasArg(options::OPT_continue_building_after_errors);

}

static Optional<unsigned>
getDriverBatchSizeLimit(llvm::opt::InputArgList &ArgList,
                        DiagnosticEngine &Diags)
{
  if (const Arg *A = ArgList.getLastArg(options::OPT_driver_batch_size_limit)) {
    unsigned Limit = 0;
    if (StringRef(A->getValue()).getAsInteger(10, Limit)) {
      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
                     A->getAsString(ArgList), A->getValue());
    } else {
      return Limit;
    }
  }
  return None;
}

std::unique_ptr<Compilation>
Driver::buildCompilation(const ToolChain &TC,
                         std::unique_ptr<llvm::opt::InputArgList> ArgList) {
  llvm::PrettyStackTraceString CrashInfo("Compilation construction");

  llvm::sys::TimePoint<> StartTime = std::chrono::system_clock::now();

  // Claim --driver-mode here, since it's already been handled.
  (void) ArgList->hasArg(options::OPT_driver_mode);

  DriverPrintBindings = ArgList->hasArg(options::OPT_driver_print_bindings);

  const std::string workingDirectory = computeWorkingDirectory(ArgList.get());

  std::unique_ptr<DerivedArgList> TranslatedArgList(
      translateInputAndPathArgs(*ArgList, workingDirectory));

  validateArgs(Diags, *TranslatedArgList, TC.getTriple());
    
  // Perform toolchain specific args validation.
  TC.validateArguments(Diags, *TranslatedArgList, DefaultTargetTriple);

  if (Diags.hadAnyError())
    return nullptr;

  if (!handleImmediateArgs(*TranslatedArgList, TC)) {
    return nullptr;
  }

  // Construct the list of inputs.
  InputFileList Inputs;
  buildInputs(TC, *TranslatedArgList, Inputs);

  if (Diags.hadAnyError())
    return nullptr;

  // Determine the OutputInfo for the driver.
  OutputInfo OI;
  bool BatchMode = false;
  OI.CompilerMode = computeCompilerMode(*TranslatedArgList, Inputs, BatchMode);
  buildOutputInfo(TC, *TranslatedArgList, BatchMode, Inputs, OI);

  if (Diags.hadAnyError())
    return nullptr;

  assert(OI.CompilerOutputType != file_types::ID::TY_INVALID &&
         "buildOutputInfo() must set a valid output type!");

  TC.validateOutputInfo(Diags, OI);
  if (Diags.hadAnyError())
    return nullptr;

  validateEmbedBitcode(*TranslatedArgList, OI, Diags);

  if (OI.CompilerMode == OutputInfo::Mode::REPL)
    // REPL mode expects no input files, so suppress the error.
    SuppressNoInputFilesError = true;

  const bool EnableSourceRangeDependencies =
      ArgList->hasArg(options::OPT_enable_source_range_dependencies);
  const bool CompareIncrementalSchemes =
      ArgList->hasArg(options::OPT_driver_compare_incremental_schemes) ||
      ArgList->hasArg(options::OPT_driver_compare_incremental_schemes_path);
  const StringRef CompareIncrementalSchemesPath = ArgList->getLastArgValue(
      options::OPT_driver_compare_incremental_schemes_path);

  Optional<OutputFileMap> OFM = buildOutputFileMap(
      *TranslatedArgList, workingDirectory,
      /*addEntriesForSourceFileDependencies=*/EnableSourceRangeDependencies ||
          CompareIncrementalSchemes);

  if (Diags.hadAnyError())
    return nullptr;

  if (ArgList->hasArg(options::OPT_driver_print_output_file_map)) {
    if (OFM)
      OFM->dump(llvm::errs(), true);
    else
      Diags.diagnose(SourceLoc(), diag::error_no_output_file_map_specified);
    return nullptr;
  }

  const bool ShowIncrementalBuildDecisions =
      ArgList->hasArg(options::OPT_driver_show_incremental);
  const bool Incremental =
      computeIncremental(ArgList.get(), ShowIncrementalBuildDecisions);

  std::string buildRecordPath;
  getCompilationRecordPath(buildRecordPath,
                           OI, OFM, Incremental ? &Diags : nullptr);

  SmallString<32> ArgsHash;
  computeArgsHash(ArgsHash, *TranslatedArgList);
  llvm::sys::TimePoint<> LastBuildTime = llvm::sys::TimePoint<>::min();
  InputInfoMap outOfDateMap;
  std::string whyIgnoreIncrementallity =
      !Incremental
          ? ""
          : buildRecordPath.empty()
                ? "no build record path"
                : populateOutOfDateMap(outOfDateMap, LastBuildTime, ArgsHash,
                                       Inputs, buildRecordPath,
                                       EnableSourceRangeDependencies,
                                       ShowIncrementalBuildDecisions);
  // FIXME: Distinguish errors from "file removed", which is benign.

  size_t DriverFilelistThreshold;
  if (getFilelistThreshold(*TranslatedArgList, DriverFilelistThreshold, Diags))
    return nullptr;

  OutputLevel Level = OutputLevel::Normal;
  if (const Arg *A =
          ArgList->getLastArg(options::OPT_driver_print_jobs, options::OPT_v,
                              options::OPT_parseable_output)) {
    if (A->getOption().matches(options::OPT_driver_print_jobs))
      Level = OutputLevel::PrintJobs;
    else if (A->getOption().matches(options::OPT_v))
      Level = OutputLevel::Verbose;
    else if (A->getOption().matches(options::OPT_parseable_output))
      Level = OutputLevel::Parseable;
    else
      llvm_unreachable("Unknown OutputLevel argument!");
  }

  
  // About to move argument list, so capture some flags that will be needed
  // later.
  const bool DriverPrintActions =
      ArgList->hasArg(options::OPT_driver_print_actions);
  const bool DriverPrintDerivedOutputFileMap =
      ArgList->hasArg(options::OPT_driver_print_derived_output_file_map);
  const bool ContinueBuildingAfterErrors =
      computeContinueBuildingAfterErrors(BatchMode, ArgList.get());
  const bool ShowJobLifecycle =
      ArgList->hasArg(options::OPT_driver_show_job_lifecycle);

  // In order to confine the values below, while still moving the argument
  // list, and preserving the interface to Compilation, enclose the call to the
  // constructor in a block:
  std::unique_ptr<Compilation> C;
  {
    const unsigned DriverBatchSeed = getDriverBatchSeed(*ArgList, Diags);
    const Optional<unsigned> DriverBatchCount =
        getDriverBatchCount(*ArgList, Diags);
    const Optional<unsigned> DriverBatchSizeLimit =
      getDriverBatchSizeLimit(*ArgList, Diags);
    const bool SaveTemps = ArgList->hasArg(options::OPT_save_temps);
    const bool ShowDriverTimeCompilation =
        ArgList->hasArg(options::OPT_driver_time_compilation);
    std::unique_ptr<UnifiedStatsReporter> StatsReporter =
        createStatsReporter(ArgList.get(), Inputs, OI, DefaultTargetTriple);

    const bool OnlyOneDependencyFile =
        ArgList->hasFlag(options::OPT_enable_only_one_dependency_file,
                         options::OPT_disable_only_one_dependency_file, false);

    const bool VerifyFineGrainedDependencyGraphAfterEveryImport = ArgList->hasArg(
        options::
            OPT_driver_verify_fine_grained_dependency_graph_after_every_import);
    const bool EmitFineGrainedDependencyDotFileAfterEveryImport = ArgList->hasArg(
        options::
            OPT_driver_emit_fine_grained_dependency_dot_file_after_every_import);
    const bool EnableCrossModuleDependencies = ArgList->hasArg(
        options::OPT_enable_experimental_cross_module_incremental_build);

    // clang-format off
    C = std::make_unique<Compilation>(
        Diags, TC, OI, Level,
        std::move(ArgList),
        std::move(TranslatedArgList),
        std::move(Inputs),
        buildRecordPath,
        ArgsHash,
        StartTime,
        LastBuildTime,
        DriverFilelistThreshold,
        Incremental,
        BatchMode,
        DriverBatchSeed,
        DriverBatchCount,
        DriverBatchSizeLimit,
        SaveTemps,
        ShowDriverTimeCompilation,
        std::move(StatsReporter),
        OnlyOneDependencyFile,
        VerifyFineGrainedDependencyGraphAfterEveryImport,
        EmitFineGrainedDependencyDotFileAfterEveryImport,
        EnableSourceRangeDependencies,
        CompareIncrementalSchemes,
        CompareIncrementalSchemesPath,
        EnableCrossModuleDependencies);
    // clang-format on
  }

  // Construct the graph of Actions.
  SmallVector<const Action *, 8> TopLevelActions;
  buildActions(TopLevelActions, TC, OI,
               whyIgnoreIncrementallity.empty() ? &outOfDateMap : nullptr, *C);

  if (Diags.hadAnyError())
    return nullptr;

  if (DriverPrintActions) {
    printActions(*C);
    return nullptr;
  }

  buildJobs(TopLevelActions, OI, OFM ? OFM.getPointer() : nullptr,
            workingDirectory, TC, *C);

  if (DriverPrintDerivedOutputFileMap) {
    C->getDerivedOutputFileMap().dump(llvm::outs(), true);
    return nullptr;
  }

  // For getting bulk fixits, or for when users explicitly request to continue
  // building despite errors.
  if (ContinueBuildingAfterErrors)
    C->setContinueBuildingAfterErrors();

  if (ShowIncrementalBuildDecisions || ShowJobLifecycle)
    C->setShowIncrementalBuildDecisions();

  if (ShowJobLifecycle)
    C->setShowJobLifecycle();

  // This has to happen after building jobs, because otherwise we won't even
  // emit .swiftdeps files for the next build.
  if (!whyIgnoreIncrementallity.empty())
    C->disableIncrementalBuild(whyIgnoreIncrementallity);

  if (Diags.hadAnyError())
    return nullptr;

  if (DriverPrintBindings)
    return nullptr;

  return C;
}

static Arg *makeInputArg(const DerivedArgList &Args, OptTable &Opts,
                         StringRef Value) {
  Arg *A = new Arg(Opts.getOption(options::OPT_INPUT), Value,
                   Args.getBaseArgs().MakeIndex(Value), Value.data());
  A->claim();
  return A;
}

using RemainingArgsHandler = llvm::function_ref<void(InputArgList &, unsigned)>;

std::unique_ptr<InputArgList>
parseArgsUntil(const llvm::opt::OptTable& Opts,
               const char *const *ArgBegin,
               const char *const *ArgEnd,
               unsigned &MissingArgIndex,
               unsigned &MissingArgCount,
               unsigned FlagsToInclude,
               unsigned FlagsToExclude,
               llvm::opt::OptSpecifier UntilOption,
               RemainingArgsHandler RemainingHandler) {
  auto Args = std::make_unique<InputArgList>(ArgBegin, ArgEnd);

  // FIXME: Handle '@' args (or at least error on them).

  bool CheckUntil = UntilOption != options::OPT_INVALID;
  MissingArgIndex = MissingArgCount = 0;
  unsigned Index = 0, End = ArgEnd - ArgBegin;
  while (Index < End) {
    // Ignore empty arguments (other things may still take them as arguments).
    StringRef Str = Args->getArgString(Index);
    if (Str == "") {
      ++Index;
      continue;
    }

    unsigned Prev = Index;
    Arg *A = Opts.ParseOneArg(*Args, Index, FlagsToInclude, FlagsToExclude);
    assert(Index > Prev && "Parser failed to consume argument.");

    // Check for missing argument error.
    if (!A) {
      assert(Index >= End && "Unexpected parser error.");
      assert(Index - Prev - 1 && "No missing arguments!");
      MissingArgIndex = Prev;
      MissingArgCount = Index - Prev - 1;
      break;
    }

    Args->append(A);

    if (CheckUntil && A->getOption().matches(UntilOption)) {
      if (Index < End)
        RemainingHandler(*Args, Index);
      return Args;
    }
  }

  return Args;
}

// Parse all args until we see an input, and then collect the remaining
// arguments into a synthesized "--" option.
static std::unique_ptr<InputArgList>
parseArgStringsForInteractiveDriver(const llvm::opt::OptTable& Opts,
                                    ArrayRef<const char *> Args,
                                    unsigned &MissingArgIndex,
                                    unsigned &MissingArgCount,
                                    unsigned FlagsToInclude,
                                    unsigned FlagsToExclude) {
  return parseArgsUntil(Opts, Args.begin(), Args.end(), MissingArgIndex,
                        MissingArgCount, FlagsToInclude, FlagsToExclude,
                        options::OPT_INPUT,
                        [&](InputArgList &Args, unsigned NextIndex) {
    assert(NextIndex < Args.getNumInputArgStrings());
    // Synthesize -- remaining args...
    Arg *Remaining =
        new Arg(Opts.getOption(options::OPT__DASH_DASH), "--", NextIndex);
    for (unsigned N = Args.getNumInputArgStrings(); NextIndex != N;
         ++NextIndex) {
      Remaining->getValues().push_back(Args.getArgString(NextIndex));
    }
    Args.append(Remaining);
  });
}

std::unique_ptr<InputArgList>
Driver::parseArgStrings(ArrayRef<const char *> Args) {
  unsigned IncludedFlagsBitmask = 0;
  unsigned ExcludedFlagsBitmask = options::NoDriverOption;
  unsigned MissingArgIndex, MissingArgCount;
  std::unique_ptr<InputArgList> ArgList;

  if (driverKind == DriverKind::Interactive) {
    ArgList = parseArgStringsForInteractiveDriver(getOpts(), Args,
        MissingArgIndex, MissingArgCount, IncludedFlagsBitmask,
        ExcludedFlagsBitmask);

  } else {
    ArgList = std::make_unique<InputArgList>(
        getOpts().ParseArgs(Args, MissingArgIndex, MissingArgCount,
                            IncludedFlagsBitmask, ExcludedFlagsBitmask));
  }

  assert(ArgList && "no argument list");

  // Check for missing argument error.
  if (MissingArgCount) {
    Diags.diagnose(SourceLoc(), diag::error_missing_arg_value,
                   ArgList->getArgString(MissingArgIndex), MissingArgCount);
    return nullptr;
  }

  // Check for unknown arguments.
  for (const Arg *A :  ArgList->filtered(options::OPT_UNKNOWN)) {
    Diags.diagnose(SourceLoc(), diag::error_unknown_arg,
                   A->getAsString(*ArgList));
  }

  // Check for unsupported options
  unsigned UnsupportedFlag = 0;
  if (driverKind == DriverKind::Interactive)
    UnsupportedFlag = options::NoInteractiveOption;
  else if (driverKind == DriverKind::Batch)
    UnsupportedFlag = options::NoBatchOption;

  if (UnsupportedFlag)
    for (const Arg *A : *ArgList)
      if (A->getOption().hasFlag(UnsupportedFlag))
        Diags.diagnose(SourceLoc(), diag::error_unsupported_option,
            ArgList->getArgString(A->getIndex()), Name,
            UnsupportedFlag == options::NoBatchOption ? "swift" : "swiftc");

  return ArgList;
}

DerivedArgList *
Driver::translateInputAndPathArgs(const InputArgList &ArgList,
                                  StringRef workingDirectory) const {
  DerivedArgList *DAL = new DerivedArgList(ArgList);

  auto addPath = [workingDirectory, DAL](Arg *A) {
    assert(A->getNumValues() == 1 && "multiple values not handled");
    StringRef path = A->getValue();
    if (workingDirectory.empty() || path == "-" ||
        llvm::sys::path::is_absolute(path)) {
      DAL->append(A);
      return;
    }

    SmallString<64> fullPath{workingDirectory};
    llvm::sys::path::append(fullPath, path);
    unsigned index = DAL->getBaseArgs().MakeIndex(fullPath);
    Arg *newArg = new Arg(A->getOption(), A->getSpelling(), index,
                          DAL->getBaseArgs().getArgString(index), A);
    DAL->AddSynthesizedArg(newArg);
    DAL->append(newArg);
  };

  for (Arg *A : ArgList) {
    if (A->getOption().hasFlag(options::ArgumentIsPath) ||
        A->getOption().matches(options::OPT_INPUT)) {
      addPath(A);
      continue;
    }

    // If we're not in immediate mode, pick up inputs via the -- option.
    if (driverKind != DriverKind::Interactive && A->getOption().matches(options::OPT__DASH_DASH)) {
      A->claim();
      for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
        addPath(makeInputArg(*DAL, *Opts, A->getValue(i)));
      }
      continue;
    }

    DAL->append(A);
  }

  return DAL;
}

/// Check that the file referenced by \p Input exists. If it doesn't,
/// issue a diagnostic and return false.
static bool checkInputExistence(const Driver &D, const DerivedArgList &Args,
                                DiagnosticEngine &Diags, StringRef Input) {
  if (!D.getCheckInputFilesExist())
    return true;

  // stdin always exists.
  if (Input == "-")
    return true;

  if (llvm::sys::fs::exists(Input))
    return true;

  Diags.diagnose(SourceLoc(), diag::error_no_such_file_or_directory, Input);
  return false;
}

void Driver::buildInputs(const ToolChain &TC,
                         const DerivedArgList &Args,
                         InputFileList &Inputs) const {
  llvm::DenseMap<StringRef, StringRef> SourceFileNames;

  for (Arg *A : Args) {
    if (A->getOption().getKind() == Option::InputClass) {
      StringRef Value = A->getValue();
      file_types::ID Ty = file_types::TY_INVALID;

      // stdin must be handled specially.
      if (Value.equals("-")) {
        // By default, treat stdin as Swift input.
        Ty = file_types::TY_Swift;
      } else {
        // Otherwise lookup by extension.
        Ty = TC.lookupTypeForExtension(llvm::sys::path::extension(Value));

        if (Ty == file_types::TY_INVALID) {
          // By default, treat inputs with no extension, or with an
          // extension that isn't recognized, as object files.
          Ty = file_types::TY_Object;
        }
      }

      if (checkInputExistence(*this, Args, Diags, Value))
        Inputs.push_back(std::make_pair(Ty, A));

      if (Ty == file_types::TY_Swift) {
        StringRef Basename = llvm::sys::path::filename(Value);
        if (!SourceFileNames.insert({Basename, Value}).second) {
          Diags.diagnose(SourceLoc(), diag::error_two_files_same_name,
                         Basename, SourceFileNames[Basename], Value);
          Diags.diagnose(SourceLoc(), diag::note_explain_two_files_same_name);
        }
      }
    }
  }
}

static bool maybeBuildingExecutable(const OutputInfo &OI,
                                    const DerivedArgList &Args,
                                    const InputFileList &Inputs) {
  switch (OI.LinkAction) {
  case LinkKind::Executable:
    return true;
  case LinkKind::DynamicLibrary:
    return false;
  case LinkKind::StaticLibrary:
    return false;
  case LinkKind::None:
    break;
  }

  if (Args.hasArg(options::OPT_parse_as_library, options::OPT_parse_stdlib))
    return false;
  return Inputs.size() == 1;
}

static void diagnoseOutputModeArg(DiagnosticEngine &diags, const Arg *arg,
                                  bool hasInputs, const DerivedArgList &args,
                                  bool isInteractiveDriver,
                                  StringRef driverName) {
  switch (arg->getOption().getID()) {

  case options::OPT_i:
    diags.diagnose(SourceLoc(), diag::error_i_mode,
                   isInteractiveDriver ? driverName : "swift");
    break;

  case options::OPT_repl:
    if (isInteractiveDriver && !hasInputs)
      diags.diagnose(SourceLoc(), diag::warning_unnecessary_repl_mode,
                     args.getArgString(arg->getIndex()), driverName);
    break;

  default:
    break;
  }
}

static bool isSDKTooOld(StringRef sdkPath, llvm::VersionTuple minVersion,
                        StringRef firstPrefix, StringRef secondPrefix = {}) {
  // FIXME: This is a hack.
  // We should be looking at the SDKSettings.plist.
  StringRef sdkDirName = llvm::sys::path::filename(sdkPath);

  size_t versionStart = sdkDirName.rfind(firstPrefix);
  if (versionStart != StringRef::npos) {
    versionStart += firstPrefix.size();
  } else if (!secondPrefix.empty()) {
    versionStart = sdkDirName.rfind(secondPrefix);
    if (versionStart != StringRef::npos)
      versionStart += secondPrefix.size();
  }
  if (versionStart == StringRef::npos)
    return false;

  size_t versionEnd = sdkDirName.rfind(".Internal");
  if (versionEnd == StringRef::npos)
    versionEnd = sdkDirName.rfind(".sdk");
  if (versionEnd == StringRef::npos)
    return false;

  llvm::VersionTuple version;
  if (version.tryParse(sdkDirName.slice(versionStart, versionEnd)))
    return false;
  return version < minVersion;
}

/// Returns true if the given SDK path points to an SDK that is too old for
/// the given target.
static bool isSDKTooOld(StringRef sdkPath, const llvm::Triple &target) {
  if (target.isMacOSX()) {
    return isSDKTooOld(sdkPath, llvm::VersionTuple(10, 15), "OSX");

  } else if (target.isiOS()) {
    // Includes both iOS and TVOS.
    return isSDKTooOld(sdkPath, llvm::VersionTuple(13, 0), "Simulator", "OS");

  } else if (target.isWatchOS()) {
    return isSDKTooOld(sdkPath, llvm::VersionTuple(6, 0), "Simulator", "OS");

  } else {
    return false;
  }
}

void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
                             const bool BatchMode, const InputFileList &Inputs,
                             OutputInfo &OI) const {

  if (const Arg *A = Args.getLastArg(options::OPT_lto)) {
    auto LTOVariant =
        llvm::StringSwitch<Optional<OutputInfo::LTOKind>>(A->getValue())
            .Case("llvm-thin", OutputInfo::LTOKind::LLVMThin)
            .Case("llvm-full", OutputInfo::LTOKind::LLVMFull)
            .Default(llvm::None);
    if (LTOVariant)
      OI.LTOVariant = LTOVariant.getValue();
    else
      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
                     A->getAsString(Args), A->getValue());
  }

  auto CompilerOutputType = OI.LTOVariant != OutputInfo::LTOKind::None
                             ? file_types::TY_LLVM_BC
                             : file_types::TY_Object;
  // By default, the driver does not link its output; this will be updated
  // appropriately below if linking is required.

  OI.CompilerOutputType = driverKind == DriverKind::Interactive
                              ? file_types::TY_Nothing
                              : CompilerOutputType;

  if (const Arg *A = Args.getLastArg(options::OPT_num_threads)) {
    if (BatchMode) {
      Diags.diagnose(SourceLoc(), diag::warning_cannot_multithread_batch_mode);
    } else if (StringRef(A->getValue()).getAsInteger(10, OI.numThreads)) {
      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
                     A->getAsString(Args), A->getValue());
    }
  }

  const Arg *const OutputModeArg = Args.getLastArg(options::OPT_modes_Group);

  if (!OutputModeArg) {
    if (Args.hasArg(options::OPT_emit_module, options::OPT_emit_module_path)) {
      OI.CompilerOutputType = file_types::TY_SwiftModuleFile;
    } else if (driverKind != DriverKind::Interactive) {
      OI.LinkAction = LinkKind::Executable;
    }
  } else {
    diagnoseOutputModeArg(Diags, OutputModeArg, !Inputs.empty(), Args,
                          driverKind == DriverKind::Interactive, Name);

    switch (OutputModeArg->getOption().getID()) {
    case options::OPT_emit_executable:
      if (Args.hasArg(options::OPT_static))
        Diags.diagnose(SourceLoc(),
                       diag::error_static_emit_executable_disallowed);
                       
      OI.LinkAction = LinkKind::Executable;
      OI.CompilerOutputType = CompilerOutputType;
      break;

    case options::OPT_emit_library:
      OI.LinkAction = Args.hasArg(options::OPT_static) ?
                      LinkKind::StaticLibrary :
                      LinkKind::DynamicLibrary;
      OI.CompilerOutputType = CompilerOutputType;
      break;

    case options::OPT_static:
      break;

    case options::OPT_emit_object:
      OI.CompilerOutputType = file_types::TY_Object;
      break;

    case options::OPT_emit_assembly:
      OI.CompilerOutputType = file_types::TY_Assembly;
      break;

    case options::OPT_emit_sil:
      OI.CompilerOutputType = file_types::TY_SIL;
      break;

    case options::OPT_emit_silgen:
      OI.CompilerOutputType = file_types::TY_RawSIL;
      break;

    case options::OPT_emit_sib:
      OI.CompilerOutputType = file_types::TY_SIB;
      break;

    case options::OPT_emit_sibgen:
      OI.CompilerOutputType = file_types::TY_RawSIB;
      break;

    case options::OPT_emit_ir:
      OI.CompilerOutputType = file_types::TY_LLVM_IR;
      break;

    case options::OPT_emit_bc:
      OI.CompilerOutputType = file_types::TY_LLVM_BC;
      break;

    case options::OPT_dump_ast:
      OI.CompilerOutputType = file_types::TY_ASTDump;
      break;

    case options::OPT_emit_pch:
      OI.CompilerMode = OutputInfo::Mode::SingleCompile;
      OI.CompilerOutputType = file_types::TY_PCH;
      break;

    case options::OPT_emit_pcm:
      OI.CompilerMode = OutputInfo::Mode::SingleCompile;
      OI.CompilerOutputType = file_types::TY_ClangModuleFile;
      break;

    case options::OPT_emit_imported_modules:
      OI.CompilerOutputType = file_types::TY_ImportedModules;
      // We want the imported modules from the module as a whole, not individual
      // files, so let's do it in one invocation rather than having to collate
      // later.
      OI.CompilerMode = OutputInfo::Mode::SingleCompile;
      break;

    case options::OPT_scan_dependencies:
      OI.CompilerOutputType = file_types::TY_JSONDependencies;
      // We want the imported modules from the module as a whole, not individual
      // files, so let's do it in one invocation rather than having to collate
      // later.
      OI.CompilerMode = OutputInfo::Mode::SingleCompile;
      break;

    case options::OPT_index_file:
      OI.CompilerMode = OutputInfo::Mode::SingleCompile;
      OI.CompilerOutputType = file_types::TY_IndexData;
      break;

    case options::OPT_update_code:
      OI.CompilerOutputType = file_types::TY_Remapping;
      OI.LinkAction = LinkKind::None;
      break;

    case options::OPT_parse:
    case options::OPT_resolve_imports:
    case options::OPT_typecheck:
    case options::OPT_dump_parse:
    case options::OPT_emit_syntax:
    case options::OPT_print_ast:
    case options::OPT_dump_type_refinement_contexts:
    case options::OPT_dump_scope_maps:
    case options::OPT_dump_interface_hash:
    case options::OPT_dump_type_info:
    case options::OPT_verify_debug_info:
      OI.CompilerOutputType = file_types::TY_Nothing;
      break;

    case options::OPT_dump_pcm:
      OI.CompilerMode = OutputInfo::Mode::SingleCompile;
      OI.CompilerOutputType = file_types::TY_Nothing;
      break;

    case options::OPT_i:
      // Keep the default output/mode; this flag was removed and should already
      // have been diagnosed above.
      assert(Diags.hadAnyError() && "-i flag was removed");
      break;

    case options::OPT_repl:
    case options::OPT_deprecated_integrated_repl:
    case options::OPT_lldb_repl:
      OI.CompilerOutputType = file_types::TY_Nothing;
      OI.CompilerMode = OutputInfo::Mode::REPL;
      break;

    default:
      llvm_unreachable("unknown mode");
    }
  }

  assert(OI.CompilerOutputType != file_types::ID::TY_INVALID);

  if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
    if (A->getOption().matches(options::OPT_g))
      OI.DebugInfoLevel = IRGenDebugInfoLevel::Normal;
    else if (A->getOption().matches(options::OPT_gline_tables_only))
      OI.DebugInfoLevel = IRGenDebugInfoLevel::LineTables;
    else if (A->getOption().matches(options::OPT_gdwarf_types))
      OI.DebugInfoLevel = IRGenDebugInfoLevel::DwarfTypes;
    else
      assert(A->getOption().matches(options::OPT_gnone) &&
             "unknown -g<kind> option");
  }

  if (const Arg *A = Args.getLastArg(options::OPT_debug_info_format)) {
    if (strcmp(A->getValue(), "dwarf") == 0)
      OI.DebugInfoFormat = IRGenDebugInfoFormat::DWARF;
    else if (strcmp(A->getValue(), "codeview") == 0)
      OI.DebugInfoFormat = IRGenDebugInfoFormat::CodeView;
    else
      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
                     A->getAsString(Args), A->getValue());
  } else if (OI.DebugInfoLevel > IRGenDebugInfoLevel::None) {
    // If -g was specified but not -debug-info-format, DWARF is assumed.
    OI.DebugInfoFormat = IRGenDebugInfoFormat::DWARF;
  }
  if (Args.hasArg(options::OPT_debug_info_format) &&
      !Args.hasArg(options::OPT_g_Group)) {
    const Arg *debugFormatArg = Args.getLastArg(options::OPT_debug_info_format);
    Diags.diagnose(SourceLoc(), diag::error_option_missing_required_argument,
                   debugFormatArg->getAsString(Args), "-g");
  }
  if (OI.DebugInfoFormat == IRGenDebugInfoFormat::CodeView &&
      (OI.DebugInfoLevel == IRGenDebugInfoLevel::LineTables ||
       OI.DebugInfoLevel == IRGenDebugInfoLevel::DwarfTypes)) {
    const Arg *debugFormatArg = Args.getLastArg(options::OPT_debug_info_format);
    Diags.diagnose(SourceLoc(), diag::error_argument_not_allowed_with,
                   debugFormatArg->getAsString(Args),
                   OI.DebugInfoLevel == IRGenDebugInfoLevel::LineTables
                     ? "-gline-tables-only"
                     : "-gdwarf_types");
  }

  if (Args.hasArg(options::OPT_emit_module, options::OPT_emit_module_path)) {
    // The user has requested a module, so generate one and treat it as
    // top-level output.
    OI.ShouldGenerateModule = true;
    OI.ShouldTreatModuleAsTopLevelOutput = true;
  } else if (OI.DebugInfoLevel > IRGenDebugInfoLevel::LineTables &&
             OI.shouldLink()) {
    // An option has been passed which requires a module, but the user hasn't
    // requested one. Generate a module, but treat it as an intermediate output.
    OI.ShouldGenerateModule = true;
    OI.ShouldTreatModuleAsTopLevelOutput = false;
  } else if (Args.hasArg(options::OPT_emit_objc_header,
                         options::OPT_emit_objc_header_path,
                         options::OPT_emit_module_interface,
                         options::OPT_emit_module_interface_path,
                         options::OPT_emit_private_module_interface_path) &&
             OI.CompilerMode != OutputInfo::Mode::SingleCompile) {
    // An option has been passed which requires whole-module knowledge, but we
    // don't have that. Generate a module, but treat it as an intermediate
    // output.
    OI.ShouldGenerateModule = true;
    OI.ShouldTreatModuleAsTopLevelOutput = false;
  } else {
    // No options require a module, so don't generate one.
    OI.ShouldGenerateModule = false;
    OI.ShouldTreatModuleAsTopLevelOutput = false;
  }

  if (OI.ShouldGenerateModule &&
      (OI.CompilerMode == OutputInfo::Mode::REPL ||
       OI.CompilerMode == OutputInfo::Mode::Immediate)) {
    Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module);
    return;
  }

  if (const Arg *A = Args.getLastArg(options::OPT_module_name)) {
    OI.ModuleName = A->getValue();
  } else if (OI.CompilerMode == OutputInfo::Mode::REPL) {
    // REPL mode should always use the REPL module.
    OI.ModuleName = "REPL";
  } else if (const Arg *A = Args.getLastArg(options::OPT_o)) {
    OI.ModuleName = llvm::sys::path::stem(A->getValue()).str();
    if ((OI.LinkAction == LinkKind::DynamicLibrary ||
         OI.LinkAction == LinkKind::StaticLibrary) &&
        !llvm::sys::path::extension(A->getValue()).empty() &&
        StringRef(OI.ModuleName).startswith("lib")) {
      // Chop off a "lib" prefix if we're building a library.
      OI.ModuleName.erase(0, strlen("lib"));
    }
  } else if (Inputs.size() == 1) {
    OI.ModuleName =
        llvm::sys::path::stem(Inputs.front().second->getValue()).str();
  }

  if (!Lexer::isIdentifier(OI.ModuleName) ||
      (OI.ModuleName == STDLIB_NAME &&
       !Args.hasArg(options::OPT_parse_stdlib))) {
    OI.ModuleNameIsFallback = true;
    if (OI.CompilerOutputType == file_types::TY_Nothing ||
        maybeBuildingExecutable(OI, Args, Inputs))
      OI.ModuleName = "main";
    else if (!Inputs.empty() || OI.CompilerMode == OutputInfo::Mode::REPL) {
      // Having an improper module name is only bad if we have inputs or if
      // we're in REPL mode.
      auto DID = (OI.ModuleName == STDLIB_NAME) ? diag::error_stdlib_module_name
                                                : diag::error_bad_module_name;
      Diags.diagnose(SourceLoc(), DID,
                     OI.ModuleName, !Args.hasArg(options::OPT_module_name));
      OI.ModuleName = "__bad__";
    }
  }

  {
    if (const Arg *A = Args.getLastArg(options::OPT_sdk)) {
      OI.SDKPath = A->getValue();
    } else if (const char *SDKROOT = getenv("SDKROOT")) {
      OI.SDKPath = SDKROOT;
    } else if (OI.CompilerMode == OutputInfo::Mode::Immediate ||
               OI.CompilerMode == OutputInfo::Mode::REPL) {
      if (TC.getTriple().isMacOSX()) {
        // In immediate modes, use the SDK provided by xcrun.
        // This will prefer the SDK alongside the Swift found by "xcrun swift".
        // We don't do this in compilation modes because defaulting to the
        // latest SDK may not be intended.
        auto xcrunPath = llvm::sys::findProgramByName("xcrun");
        if (!xcrunPath.getError()) {
          const char *args[] = {
            "--show-sdk-path", "--sdk", "macosx", nullptr
          };
          sys::TaskQueue queue;
          queue.addTask(xcrunPath->c_str(), args);
          queue.execute(nullptr,
                        [&OI](sys::ProcessId PID, int returnCode,
                              StringRef output, StringRef errors,
                              sys::TaskProcessInformation ProcInfo,
                              void *unused) -> sys::TaskFinishedResponse {
            if (returnCode == 0) {
              output = output.rtrim();
              auto lastLineStart = output.find_last_of("\n\r");
              if (lastLineStart != StringRef::npos)
                output = output.substr(lastLineStart+1);
              if (output.empty())
                OI.SDKPath = "/";
              else
                OI.SDKPath = output.str();
            }
            return sys::TaskFinishedResponse::ContinueExecution;
          });
        }
      }
    }

    if (!OI.SDKPath.empty()) {
      // Delete a trailing /.
      if (OI.SDKPath.size() > 1 &&
          llvm::sys::path::is_separator(OI.SDKPath.back())) {
        OI.SDKPath.erase(OI.SDKPath.end()-1);
      }

      if (!llvm::sys::fs::exists(OI.SDKPath)) {
        Diags.diagnose(SourceLoc(), diag::warning_no_such_sdk, OI.SDKPath);
      } else if (isSDKTooOld(OI.SDKPath, TC.getTriple())) {
        Diags.diagnose(SourceLoc(), diag::error_sdk_too_old,
                       llvm::sys::path::filename(OI.SDKPath));
      }
    }
  }

  if (const Arg *A = Args.getLastArg(options::OPT_sanitize_EQ))
    OI.SelectedSanitizers = parseSanitizerArgValues(
        Args, A, TC.getTriple(), Diags,
        [&](StringRef sanitizerName, bool shared) {
          return TC.sanitizerRuntimeLibExists(Args, sanitizerName, shared);
        });

  if (const Arg *A = Args.getLastArg(options::OPT_sanitize_recover_EQ)) {
    // Just validate the args. The frontend will parse these again and actually
    // use them. To avoid emitting warnings multiple times we surpress warnings
    // here but not in the frontend.
    (void)parseSanitizerRecoverArgValues(A, OI.SelectedSanitizers, Diags,
                                         /*emitWarnings=*/false);
  }

  if (const Arg *A = Args.getLastArg(options::OPT_sanitize_coverage_EQ)) {

    // Check that the sanitizer coverage flags are supported if supplied.
    // Dismiss the output, as we will grab the value later.
    (void)parseSanitizerCoverageArgValue(A, TC.getTriple(), Diags,
                                         OI.SelectedSanitizers);

  }

  if (TC.getTriple().isOSWindows()) {
    if (const Arg *A = Args.getLastArg(options::OPT_libc)) {
      OI.RuntimeVariant =
          llvm::StringSwitch<Optional<OutputInfo::MSVCRuntime>>(A->getValue())
              .Cases("MD", "MultiThreadedDLL", "shared-ucrt",
                     OutputInfo::MSVCRuntime::MultiThreadedDLL)
              .Cases("MDd", "MultiThreadedDebugDLL", "shared-debug-ucrt",
                     OutputInfo::MSVCRuntime::MultiThreadedDebugDLL)
              .Cases("MT", "MultiThreaded", "static-ucrt",
                     OutputInfo::MSVCRuntime::MultiThreaded)
              .Cases("MTd", "MultiThreadedDebug", "static-debug-ucrt",
                     OutputInfo::MSVCRuntime::MultiThreadedDebug)
              .Default(llvm::None);
      if (!OI.RuntimeVariant)
        Diags.diagnose({}, diag::error_invalid_arg_value, A->getSpelling(),
                       A->getValue());
    } else {
      // NOTE: default to `/MD`.  This is different from `cl`'s default
      // behaviour of `/MT` on the command line, however, Visual Studio 2015 and
      // newer will default `/MD` as well.  Furthermore, this is far more useful
      // of a mode since the `/MT` mode requires that everything is statically
      // linked.
      OI.RuntimeVariant = OutputInfo::MSVCRuntime::MultiThreadedDLL;
    }
  }
}

OutputInfo::Mode
Driver::computeCompilerMode(const DerivedArgList &Args,
                            const InputFileList &Inputs,
                            bool &BatchModeOut) const {

  if (driverKind == Driver::DriverKind::Interactive)
    return Inputs.empty() ? OutputInfo::Mode::REPL
                          : OutputInfo::Mode::Immediate;

  bool UseWMO = Args.hasFlag(options::OPT_whole_module_optimization,
                             options::OPT_no_whole_module_optimization,
                             false);

  const Arg *ArgRequiringSingleCompile = Args.getLastArg(
      options::OPT_index_file,
      UseWMO ? options::OPT_whole_module_optimization : llvm::opt::OptSpecifier());

  BatchModeOut = Args.hasFlag(options::OPT_enable_batch_mode,
                              options::OPT_disable_batch_mode,
                              false);

  // For best unparsed ranges, want non-batch mode, standard compile
  const Arg *ArgRequiringSinglePrimaryCompile =
      Args.getLastArg(options::OPT_enable_source_range_dependencies);

  // AST dump doesn't work with `-wmo`. Since it's not common to want to dump
  // the AST, we assume that's the priority and ignore `-wmo`, but we warn the
  // user about this decision.
  // FIXME: AST dump also doesn't work with `-index-file`, but that fix is a bit
  // more complicated than this.
  if (UseWMO && Args.hasArg(options::OPT_dump_ast)) {
    Diags.diagnose(SourceLoc(), diag::warn_ignoring_wmo);
    return OutputInfo::Mode::StandardCompile;
  }

  // Override batch mode if given -wmo or -index-file.
  if (ArgRequiringSingleCompile) {
    if (BatchModeOut) {
      BatchModeOut = false;
      // Emit a warning about such overriding (FIXME: we might conditionalize
      // this based on the user or xcode passing -disable-batch-mode).
      Diags.diagnose(SourceLoc(), diag::warn_ignoring_batch_mode,
                     ArgRequiringSingleCompile->getOption().getPrefixedName());
    }
    if (ArgRequiringSinglePrimaryCompile)
      Diags.diagnose(SourceLoc(), diag::warn_ignoring_source_range_dependencies,
                     ArgRequiringSingleCompile->getOption().getPrefixedName());
    return OutputInfo::Mode::SingleCompile;
  }

  return OutputInfo::Mode::StandardCompile;
}

namespace {
/// Encapsulates the computation of input jobs that are relevant to the
/// merge-modules job the scheduler can insert if we are not in a single compile
/// mode.
class ModuleInputs final {
private:
  using InputInfo = IncrementalJobAction::InputInfo;
  SmallVector<const Action *, 2> AllModuleInputs;
  InputInfo StatusBound;

public:
  explicit ModuleInputs()
      : StatusBound
            {InputInfo::Status::UpToDate, llvm::sys::TimePoint<>::min()} {}

public:
  void addInput(const Action *inputAction) {
    if (auto *IJA = dyn_cast<IncrementalJobAction>(inputAction)) {
      // Take the upper bound of the status of any incremental inputs to
      // ensure that the merge-modules job gets run if *any* input job is run.
      const auto conservativeStatus =
          std::max(StatusBound.status, IJA->getInputInfo().status);
      // The modification time here is not important to the rest of the
      // incremental build. We take the upper bound in case an attempt to
      // compare the swiftmodule output's mod time and any input files is
      // made. If the compilation has been correctly scheduled, the
      // swiftmodule's mod time will always strictly exceed the mod time of
      // any of its inputs when we are able to skip it.
      const auto conservativeModTime = std::max(
          StatusBound.previousModTime, IJA->getInputInfo().previousModTime);
      StatusBound = InputInfo{conservativeStatus, conservativeModTime};
    }
    AllModuleInputs.push_back(inputAction);
  }

public:
  /// Returns \c true if no inputs have been registered with this instance.
  bool empty() const { return AllModuleInputs.empty(); }

public:
  /// Consumes this \c ModuleInputs instance and returns a merge-modules action
  /// from the list of input actions and status it has computed thus far.
  JobAction *intoAction(Compilation &C) && {
    return C.createAction<MergeModuleJobAction>(AllModuleInputs, StatusBound);
  }
};
} // namespace

void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
                          const ToolChain &TC, const OutputInfo &OI,
                          const InputInfoMap *OutOfDateMap,
                          Compilation &C) const {
  const DerivedArgList &Args = C.getArgs();
  ArrayRef<InputPair> Inputs = C.getInputFiles();

  if (!SuppressNoInputFilesError && Inputs.empty()) {
    Diags.diagnose(SourceLoc(), diag::error_no_input_files);
    return;
  }

  ModuleInputs AllModuleInputs;
  SmallVector<const Action *, 2> AllLinkerInputs;

  switch (OI.CompilerMode) {
  case OutputInfo::Mode::StandardCompile: {

    // If the user is importing a textual (.h) bridging header and we're in
    // standard-compile (non-WMO) mode, we take the opportunity to precompile
    // the header into a temporary PCH, and replace the import argument with the
    // PCH in the subsequent frontend jobs.
    JobAction *PCH = nullptr;
    if (Args.hasFlag(options::OPT_enable_bridging_pch,
                     options::OPT_disable_bridging_pch,
                     true)) {
      if (Arg *A = Args.getLastArg(options::OPT_import_objc_header)) {
        StringRef Value = A->getValue();
        auto Ty = TC.lookupTypeForExtension(llvm::sys::path::extension(Value));
        if (Ty == file_types::TY_ObjCHeader) {
          auto *HeaderInput = C.createAction<InputAction>(*A, Ty);
          StringRef PersistentPCHDir;
          if (const Arg *A = Args.getLastArg(options::OPT_pch_output_dir)) {
            PersistentPCHDir = A->getValue();
          }
          PCH = C.createAction<GeneratePCHJobAction>(HeaderInput,
                                                     PersistentPCHDir);
        }
      }
    }

    for (const InputPair &Input : Inputs) {
      file_types::ID InputType = Input.first;
      const Arg *InputArg = Input.second;

      Action *Current = C.createAction<InputAction>(*InputArg, InputType);
      switch (InputType) {
      case file_types::TY_Swift:
      case file_types::TY_SIL:
      case file_types::TY_SIB: {
        // Source inputs always need to be compiled.
        assert(file_types::isPartOfSwiftCompilation(InputType));

        auto previousBuildState =
            IncrementalJobAction::InputInfo::makeNeedsCascadingRebuild();
        if (OutOfDateMap)
          previousBuildState = OutOfDateMap->lookup(InputArg);
        if (Args.hasArg(options::OPT_embed_bitcode)) {
          Current = C.createAction<CompileJobAction>(
              Current, file_types::TY_LLVM_BC, previousBuildState);
          if (PCH)
            cast<JobAction>(Current)->addInput(PCH);
          AllModuleInputs.addInput(Current);
          Current = C.createAction<BackendJobAction>(Current,
                                                     OI.CompilerOutputType, 0);
        } else {
          Current = C.createAction<CompileJobAction>(Current,
                                                     OI.CompilerOutputType,
                                                     previousBuildState);
          if (PCH)
            cast<JobAction>(Current)->addInput(PCH);
          AllModuleInputs.addInput(Current);
        }
        AllLinkerInputs.push_back(Current);
        break;
      }
      case file_types::TY_SwiftModuleFile:
      case file_types::TY_SwiftModuleDocFile:
      case file_types::TY_SwiftSourceInfoFile:
        if (OI.ShouldGenerateModule && !OI.shouldLink()) {
          // When generating a .swiftmodule as a top-level output (as opposed
          // to, for example, linking an image), treat .swiftmodule files as
          // inputs to a MergeModule action.
          AllModuleInputs.addInput(Current);
          break;
        } else if (OI.shouldLink()) {
          // Otherwise, if linking, pass .swiftmodule files as inputs to the
          // linker, so that their debug info is available.
          AllLinkerInputs.push_back(Current);
          break;
        } else {
          Diags.diagnose(SourceLoc(), diag::error_unexpected_input_file,
                         InputArg->getValue());
          continue;
        }
      case file_types::TY_AutolinkFile:
      case file_types::TY_Object:
      case file_types::TY_TBD:
        // Object inputs are only okay if linking.
        if (OI.shouldLink()) {
          AllLinkerInputs.push_back(Current);
          break;
        }
        LLVM_FALLTHROUGH;
      case file_types::TY_ASTDump:
      case file_types::TY_Image:
      case file_types::TY_dSYM:
      case file_types::TY_Dependencies:
      case file_types::TY_Assembly:
      case file_types::TY_LLVM_IR:
      case file_types::TY_LLVM_BC:
      case file_types::TY_SerializedDiagnostics:
      case file_types::TY_ObjCHeader:
      case file_types::TY_ClangModuleFile:
      case file_types::TY_SwiftDeps:
      case file_types::TY_ExternalSwiftDeps:
      case file_types::TY_SwiftRanges:
      case file_types::TY_CompiledSource:
      case file_types::TY_Remapping:
      case file_types::TY_IndexData:
      case file_types::TY_PCH:
      case file_types::TY_ImportedModules:
      case file_types::TY_ModuleTrace:
      case file_types::TY_YAMLOptRecord:
      case file_types::TY_BitstreamOptRecord:
      case file_types::TY_SwiftModuleInterfaceFile:
      case file_types::TY_PrivateSwiftModuleInterfaceFile:
      case file_types::TY_SwiftModuleSummaryFile:
      case file_types::TY_SwiftCrossImportDir:
      case file_types::TY_SwiftOverlayFile:
      case file_types::TY_JSONDependencies:
      case file_types::TY_JSONFeatures:
        // We could in theory handle assembly or LLVM input, but let's not.
        // FIXME: What about LTO?
        Diags.diagnose(SourceLoc(), diag::error_unexpected_input_file,
                       InputArg->getValue());
        continue;
      case file_types::TY_RawSIB:
      case file_types::TY_RawSIL:
      case file_types::TY_Nothing:
      case file_types::TY_INVALID:
        llvm_unreachable("these types should never be inferred");
      }
    }
    break;
  }
  case OutputInfo::Mode::SingleCompile: {
    if (Inputs.empty()) break;
    if (Args.hasArg(options::OPT_emit_pcm) && Inputs.size() != 1) {
      // -emit-pcm mode requires exactly one input (the module map).
      Diags.diagnose(SourceLoc(), diag::error_mode_requires_one_input_file);
      return;
    }
    if (Args.hasArg(options::OPT_embed_bitcode)) {
      // Make sure we can handle the inputs.
      bool HandledHere = true;
      for (const InputPair &Input : Inputs) {
        file_types::ID InputType = Input.first;
        if (!file_types::isPartOfSwiftCompilation(InputType)) {
          HandledHere = false;
          break;
        }
      }
      if (HandledHere) {
        // Create a single CompileJobAction and a single BackendJobAction.
        JobAction *CA =
            C.createAction<CompileJobAction>(file_types::TY_LLVM_BC);
        AllModuleInputs.addInput(CA);

        int InputIndex = 0;
        for (const InputPair &Input : Inputs) {
          file_types::ID InputType = Input.first;
          const Arg *InputArg = Input.second;

          CA->addInput(C.createAction<InputAction>(*InputArg, InputType));
          if (OI.isMultiThreading()) {
            // With multi-threading we need a backend job for each output file
            // of the compilation.
            auto *BJA = C.createAction<BackendJobAction>(CA,
                                                         OI.CompilerOutputType,
                                                         InputIndex);
            AllLinkerInputs.push_back(BJA);
          }
          ++InputIndex;
        }
        if (!OI.isMultiThreading()) {
          // No multi-threading: the compilation only produces a single output
          // file.
          CA = C.createAction<BackendJobAction>(CA, OI.CompilerOutputType, 0);
          AllLinkerInputs.push_back(CA);
        }
        break;
      }
    }

    // Create a single CompileJobAction for all of the driver's inputs.
    auto *CA = C.createAction<CompileJobAction>(OI.CompilerOutputType);
    for (const InputPair &Input : Inputs) {
      file_types::ID InputType = Input.first;
      const Arg *InputArg = Input.second;

      CA->addInput(C.createAction<InputAction>(*InputArg, InputType));
    }
    AllModuleInputs.addInput(CA);
    AllLinkerInputs.push_back(CA);
    break;
  }
  case OutputInfo::Mode::BatchModeCompile: {
    llvm_unreachable("Batch mode should not be used to build actions");
  }
  case OutputInfo::Mode::Immediate: {
    if (Inputs.empty())
      return;

    assert(OI.CompilerOutputType == file_types::TY_Nothing);
    auto *CA = C.createAction<InterpretJobAction>();
    for (const InputPair &Input : Inputs) {
      file_types::ID InputType = Input.first;
      const Arg *InputArg = Input.second;

      CA->addInput(C.createAction<InputAction>(*InputArg, InputType));
    }
    TopLevelActions.push_back(CA);
    return;
  }
  case OutputInfo::Mode::REPL: {
    if (!Inputs.empty()) {
      // REPL mode requires no inputs.
      Diags.diagnose(SourceLoc(), diag::error_repl_requires_no_input_files);
      return;
    }

    REPLJobAction::Mode Mode = REPLJobAction::Mode::PreferLLDB;
    if (const Arg *A = Args.getLastArg(options::OPT_lldb_repl,
                                       options::OPT_deprecated_integrated_repl)) {
      if (A->getOption().matches(options::OPT_lldb_repl))
        Mode = REPLJobAction::Mode::RequireLLDB;
      else
        Mode = REPLJobAction::Mode::Integrated;
    }

    TopLevelActions.push_back(C.createAction<REPLJobAction>(Mode));
    return;
  }
  }

  JobAction *MergeModuleAction = nullptr;
  if (OI.ShouldGenerateModule &&
      OI.CompilerMode != OutputInfo::Mode::SingleCompile &&
      !AllModuleInputs.empty()) {
    // We're performing multiple compilations; set up a merge module step
    // so we generate a single swiftmodule as output.
    MergeModuleAction = std::move(AllModuleInputs).intoAction(C);
  }

  bool shouldPerformLTO = OI.LTOVariant != OutputInfo::LTOKind::None;
  if (OI.shouldLink() && !AllLinkerInputs.empty()) {
    JobAction *LinkAction = nullptr;

    if (OI.LinkAction == LinkKind::StaticLibrary) {
      LinkAction =
          C.createAction<StaticLinkJobAction>(AllLinkerInputs, OI.LinkAction);
    } else {
      LinkAction = C.createAction<DynamicLinkJobAction>(
          AllLinkerInputs, OI.LinkAction, shouldPerformLTO);
    }

    // On ELF platforms there's no built in autolinking mechanism, so we
    // pull the info we need from the .o files directly and pass them as an
    // argument input file to the linker.
    const auto &Triple = TC.getTriple();
    SmallVector<const Action *, 2> AutolinkExtractInputs;
    for (const Action *A : AllLinkerInputs)
      if (A->getType() == file_types::TY_Object) {
        // Shared objects on ELF platforms don't have a swift1_autolink_entries
        // section in them because the section in the .o files is marked as
        // SHF_EXCLUDE.
        if (auto *IA = dyn_cast<InputAction>(A)) {
          StringRef ObjectName = IA->getInputArg().getValue();
          if (Triple.getObjectFormat() == llvm::Triple::ELF &&
              ObjectName.endswith(".so"))
            continue;
        }
        AutolinkExtractInputs.push_back(A);
      }
    const bool AutolinkExtractRequired =
        ((Triple.getObjectFormat() == llvm::Triple::ELF && !Triple.isPS4()) ||
         Triple.getObjectFormat() == llvm::Triple::Wasm ||
         Triple.isOSCygMing()) &&
        !shouldPerformLTO;
    if (!AutolinkExtractInputs.empty() && AutolinkExtractRequired) {
      auto *AutolinkExtractAction =
          C.createAction<AutolinkExtractJobAction>(AutolinkExtractInputs);
      // Takes the same inputs as the linker...
      // ...and gives its output to the linker.
      LinkAction->addInput(AutolinkExtractAction);
    }

    if (MergeModuleAction) {
      if (OI.DebugInfoLevel == IRGenDebugInfoLevel::Normal) {
        const bool ModuleWrapRequired =
            Triple.getObjectFormat() != llvm::Triple::MachO;
        if (ModuleWrapRequired) {
          auto *ModuleWrapAction =
              C.createAction<ModuleWrapJobAction>(MergeModuleAction);
          LinkAction->addInput(ModuleWrapAction);
        } else {
          LinkAction->addInput(MergeModuleAction);
        }
        // FIXME: Adding the MergeModuleAction as top-level regardless would
        // allow us to get rid of the special case flag for that.
      } else {
        TopLevelActions.push_back(MergeModuleAction);
      }
    }
    TopLevelActions.push_back(LinkAction);

    if (TC.getTriple().isOSDarwin() &&
        OI.DebugInfoLevel > IRGenDebugInfoLevel::None) {
      auto *dSYMAction = C.createAction<GenerateDSYMJobAction>(LinkAction);
      TopLevelActions.push_back(dSYMAction);
      if (Args.hasArg(options::OPT_verify_debug_info)) {
        TopLevelActions.push_back(
            C.createAction<VerifyDebugInfoJobAction>(dSYMAction));
      }
    }
  } else {
    // We can't rely on the merge module action being the only top-level
    // action that needs to run. There may be other actions (e.g.
    // BackendJobActions) that are not merge-module inputs but should be run
    // anyway.
    if (MergeModuleAction)
      TopLevelActions.push_back(MergeModuleAction);
    TopLevelActions.append(AllLinkerInputs.begin(), AllLinkerInputs.end());
  }

#ifdef NDEBUG
  bool verifyInterfacesByDefault = false;
#else
  bool verifyInterfacesByDefault = true;
#endif

  if (MergeModuleAction
      && Args.hasArg(options::OPT_enable_library_evolution)
      && Args.hasFlag(options::OPT_verify_emitted_module_interface,
                      options::OPT_no_verify_emitted_module_interface,
                      verifyInterfacesByDefault)) {
    if (Args.hasArgNoClaim(options::OPT_emit_module_interface,
                           options::OPT_emit_module_interface_path)) {
      TopLevelActions.push_back(
          C.createAction<VerifyModuleInterfaceJobAction>(MergeModuleAction,
              file_types::TY_SwiftModuleInterfaceFile));
    }

    if (Args.hasArgNoClaim(options::OPT_emit_private_module_interface_path)) {
      TopLevelActions.push_back(
          C.createAction<VerifyModuleInterfaceJobAction>(MergeModuleAction,
              file_types::TY_PrivateSwiftModuleInterfaceFile));
    }
  }
}

bool Driver::handleImmediateArgs(const ArgList &Args, const ToolChain &TC) {
  if (Args.hasArg(options::OPT_help)) {
    printHelp(false);
    return false;
  }

  if (Args.hasArg(options::OPT_help_hidden)) {
    printHelp(true);
    return false;
  }

  if (Args.hasArg(options::OPT_version)) {
    // Follow gcc/clang behavior and use stdout for --version and stderr for -v.
    printVersion(TC, llvm::outs());
    return false;
  }

  if (Args.hasArg(options::OPT_v)) {
    printVersion(TC, llvm::errs());
    SuppressNoInputFilesError = true;
  }

  if (const Arg *A = Args.getLastArg(options::OPT_driver_use_frontend_path)) {
    DriverExecutable = A->getValue();
    std::string commandString =
        Args.getLastArgValue(options::OPT_driver_use_frontend_path).str();
    SmallVector<StringRef, 10> commandArgs;
    StringRef(commandString).split(commandArgs, ';', -1, false);
    DriverExecutable = commandArgs[0].str();
    DriverExecutableArgs.assign(std::begin(commandArgs) + 1,
                                std::end(commandArgs));
  }

  if (Args.hasArg(options::OPT_print_target_info)) {
    SmallVector<const char *, 5> commandLine;
    commandLine.push_back("-frontend");
    commandLine.push_back("-print-target-info");
    if (const Arg *targetArg = Args.getLastArg(options::OPT_target)) {
      commandLine.push_back("-target");
      commandLine.push_back(targetArg->getValue());
    }
    if (const Arg *targetVariantArg =
            Args.getLastArg(options::OPT_target_variant)) {
      commandLine.push_back("-target-variant");
      commandLine.push_back(targetVariantArg->getValue());
    }
    if (const Arg *sdkArg = Args.getLastArg(options::OPT_sdk)) {
      commandLine.push_back("-sdk");
      commandLine.push_back(sdkArg->getValue());
    }

    if (const Arg *resourceDirArg = Args.getLastArg(options::OPT_resource_dir)) {
      commandLine.push_back("-resource-dir");
      commandLine.push_back(resourceDirArg->getValue());
    }

    if (Args.hasFlag(options::OPT_static_executable,
                     options::OPT_no_static_executable, false) ||
        Args.hasFlag(options::OPT_static_stdlib, options::OPT_no_static_stdlib,
                     false)) {
      commandLine.push_back("-use-static-resource-dir");
    }

    std::string executable = getSwiftProgramPath();

    // FIXME: This bypasses mechanisms like -v and -###. (SR-12119)
    sys::TaskQueue queue;
    queue.addTask(executable.c_str(), commandLine);
    queue.execute(nullptr,
                  [](sys::ProcessId PID, int returnCode,
                      StringRef output, StringRef errors,
                      sys::TaskProcessInformation ProcInfo,
                      void *unused) -> sys::TaskFinishedResponse {
      llvm::outs() << output;
      llvm::errs() << errors;
      return sys::TaskFinishedResponse::ContinueExecution;
    });
    return false;
  }

  return true;
}

Optional<OutputFileMap>
Driver::buildOutputFileMap(const llvm::opt::DerivedArgList &Args,
                           StringRef workingDirectory,
                           bool addEntriesForSourceFileDependencies) const {
  const Arg *A = Args.getLastArg(options::OPT_output_file_map);
  if (!A)
    return None;

  // TODO: perform some preflight checks to ensure the file exists.
  llvm::Expected<OutputFileMap> OFM = OutputFileMap::loadFromPath(
      A->getValue(), workingDirectory, addEntriesForSourceFileDependencies);
  if (auto Err = OFM.takeError()) {
    Diags.diagnose(SourceLoc(), diag::error_unable_to_load_output_file_map,
                   llvm::toString(std::move(Err)), A->getValue());
    return None;
  }
  return *OFM;
}

void Driver::buildJobs(ArrayRef<const Action *> TopLevelActions,
                       const OutputInfo &OI, const OutputFileMap *OFM,
                       StringRef workingDirectory, const ToolChain &TC,
                       Compilation &C) const {
  llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");

  const DerivedArgList &Args = C.getArgs();
  JobCacheMap JobCache;

  if (Args.hasArg(options::OPT_o) && !OI.shouldLink() &&
      !OI.ShouldTreatModuleAsTopLevelOutput) {
    bool ShouldComplain;
    if (OI.isMultiThreading()) {
      // Multi-threading compilation has multiple outputs unless there's only
      // one input.
      ShouldComplain = C.getInputFiles().size() > 1;
    } else {
      // Single-threaded compilation is a problem if we're compiling more than
      // one file.
      ShouldComplain = 1 < llvm::count_if(C.getActions(), [](const Action *A) {
        return isa<CompileJobAction>(A);
      });
    }

    if (ShouldComplain) {
      Diags.diagnose(SourceLoc(),
                     diag::error_cannot_specify__o_for_multiple_outputs);
    }
  }

  // SWIFT_ENABLE_TENSORFLOW
  for (const Action *A : TopLevelActions) {
    if (A->getKind() == Action::Kind::REPLJob) {
      Diags.diagnose(SourceLoc(),
                     diag::error_tensorflow_toolchain_repl_not_supported);
      return;
    }
  }

  for (const Action *A : TopLevelActions) {
    if (auto *JA = dyn_cast<JobAction>(A)) {
      (void)buildJobsForAction(C, JA, OFM, workingDirectory, /*TopLevel=*/true,
                               JobCache);
    }
  }
}

/// Form a filename based on \p base in \p result, optionally setting its
/// extension to \p newExt and in \p workingDirectory.
static void formFilenameFromBaseAndExt(StringRef base, StringRef newExt,
                                       StringRef workingDirectory,
                                       SmallVectorImpl<char> &result) {
  if (workingDirectory.empty() || llvm::sys::path::is_absolute(base)) {
    result.assign(base.begin(), base.end());
  } else {
    assert(!base.empty() && base != "-" && "unexpected basename");
    result.assign(workingDirectory.begin(), workingDirectory.end());
    llvm::sys::path::append(result, base);
  }

  if (!newExt.empty()) {
    llvm::sys::path::replace_extension(result, newExt);
  }
}

static Optional<StringRef> getOutputFilenameFromPathArgOrAsTopLevel(
    const OutputInfo &OI, const llvm::opt::DerivedArgList &Args,
    llvm::opt::OptSpecifier PathArg, file_types::ID ExpectedOutputType,
    bool TreatAsTopLevelOutput, StringRef workingDirectory,
    llvm::SmallString<128> &Buffer) {
  if (const Arg *A = Args.getLastArg(PathArg))
    return StringRef(A->getValue());

  if (TreatAsTopLevelOutput) {
    if (const Arg *A = Args.getLastArg(options::OPT_o)) {
      if (OI.CompilerOutputType == ExpectedOutputType)
        return StringRef(A->getValue());

      // Otherwise, put the file next to the top-level output.
      Buffer = A->getValue();
      llvm::sys::path::remove_filename(Buffer);
      llvm::sys::path::append(Buffer, OI.ModuleName);
      llvm::sys::path::replace_extension(
          Buffer, file_types::getExtension(ExpectedOutputType));
      return Buffer.str();
    }

    // A top-level output wasn't specified, so just output to
    // <ModuleName>.<ext>.
    formFilenameFromBaseAndExt(OI.ModuleName,
                               file_types::getExtension(ExpectedOutputType),
                               workingDirectory,
                               Buffer);
    return Buffer.str();
  }

  return None;
}

static StringRef assignOutputName(Compilation &C, const JobAction *JA,
                                  llvm::SmallString<128> &Buffer,
                                  StringRef BaseName,
                                  PreserveOnSignal ShouldPreserveOnSignal) {
  // We should output to a temporary file, since we're not at the top level
  // (or are generating a bridging PCH, which is currently always a temp).
  StringRef Stem = llvm::sys::path::stem(BaseName);
  StringRef Suffix = file_types::getExtension(JA->getType());
  std::error_code EC = llvm::sys::fs::createTemporaryFile(Stem, Suffix, Buffer);
  if (EC) {
    C.getDiags().diagnose(SourceLoc(),
                          diag::error_unable_to_make_temporary_file,
                          EC.message());
    return {};
  }
  C.addTemporaryFile(Buffer.str(), ShouldPreserveOnSignal);

  return Buffer.str();
}

static StringRef baseNameForImage(const JobAction *JA, const OutputInfo &OI,
                                  const llvm::Triple &Triple,
                                  llvm::SmallString<128> &Buffer,
                                  StringRef BaseInput, StringRef BaseName) {
  if (JA->size() == 1 && OI.ModuleNameIsFallback && BaseInput != "-")
    return llvm::sys::path::stem(BaseInput);
  
  if (isa<StaticLinkJobAction>(JA)) {
    Buffer = "lib";
    Buffer.append(BaseName);
    Buffer.append(Triple.isOSWindows() ? ".lib" : ".a");
    return Buffer.str();
  }
  
  auto link = dyn_cast<DynamicLinkJobAction>(JA);
  if (!link)
    return BaseName;
  if (link->getKind() != LinkKind::DynamicLibrary)
    return BaseName;

  Buffer = Triple.isOSWindows() ? "" : "lib";
  Buffer.append(BaseName);

  if (Triple.isOSDarwin())
    Buffer.append(".dylib");
  else if (Triple.isOSWindows())
    Buffer.append(".dll");
  else
    Buffer.append(".so");
  return Buffer.str();
}

static StringRef getOutputFilename(Compilation &C,
                                   const JobAction *JA,
                                   const TypeToPathMap *OutputMap,
                                   StringRef workingDirectory,
                                   bool AtTopLevel,
                                   StringRef BaseInput,
                                   StringRef PrimaryInput,
                                   llvm::SmallString<128> &Buffer) {
  if (JA->getType() == file_types::TY_Nothing)
    return {};

  // If available, check the OutputMap first.
  if (OutputMap) {
    auto iter = OutputMap->find(JA->getType());
    if (iter != OutputMap->end())
      return iter->second;
  }

  // Process Action-specific output-specifying options next,
  // since we didn't find anything applicable in the OutputMap.
  const OutputInfo &OI = C.getOutputInfo();
  const llvm::opt::DerivedArgList &Args = C.getArgs();

  if (isa<MergeModuleJobAction>(JA)) {
    auto optFilename = getOutputFilenameFromPathArgOrAsTopLevel(
        OI, Args, options::OPT_emit_module_path, file_types::TY_SwiftModuleFile,
        OI.ShouldTreatModuleAsTopLevelOutput, workingDirectory, Buffer);
    if (optFilename)
      return *optFilename;
  }

  // dSYM actions are never treated as top-level.
  if (isa<GenerateDSYMJobAction>(JA)) {
    Buffer = PrimaryInput;
    Buffer.push_back('.');
    Buffer.append(file_types::getExtension(JA->getType()));
    return Buffer.str();
  }

  auto ShouldPreserveOnSignal = PreserveOnSignal::No;

  if (auto *PCHAct = dyn_cast<GeneratePCHJobAction>(JA)) {
    // For a persistent PCH we don't use an output, the frontend determines
    // the filename to use for the PCH.
    assert(!PCHAct->isPersistentPCH());
    ShouldPreserveOnSignal = PreserveOnSignal::Yes;
  }

  // We don't have an output from an Action-specific command line option,
  // so figure one out using the defaults.
  if (AtTopLevel) {
    if (Arg *FinalOutput = Args.getLastArg(options::OPT_o))
      return FinalOutput->getValue();
    if (file_types::isTextual(JA->getType()))
      return "-";
  }

  assert(!BaseInput.empty() &&
         "A Job which produces output must have a BaseInput!");
  StringRef BaseName(BaseInput);
  if (isa<MergeModuleJobAction>(JA) ||
      (OI.CompilerMode == OutputInfo::Mode::SingleCompile &&
       !OI.isMultiThreading()) ||
      JA->getType() == file_types::TY_Image)
    BaseName = OI.ModuleName;

  // We don't yet have a name, assign one.
  if (!AtTopLevel)
    return assignOutputName(C, JA, Buffer, BaseName, ShouldPreserveOnSignal);

  if (JA->getType() == file_types::TY_Image) {
    const llvm::Triple &Triple = C.getToolChain().getTriple();
    SmallString<16> Base =
        baseNameForImage(JA, OI, Triple, Buffer, BaseInput, BaseName);
    formFilenameFromBaseAndExt(Base, /*newExt=*/"", workingDirectory, Buffer);
    return Buffer.str();
  }

  StringRef Suffix = file_types::getExtension(JA->getType());
  assert(Suffix.data() &&
         "All types used for output should have a suffix.");

  formFilenameFromBaseAndExt(llvm::sys::path::filename(BaseName), Suffix,
                             workingDirectory, Buffer);
  return Buffer.str();
}

static bool hasExistingAdditionalOutput(CommandOutput &output,
                                        file_types::ID outputType,
                                        StringRef outputPath = StringRef()) {

  auto existing = output.getAdditionalOutputForType(outputType);
  if (!existing.empty()) {
    assert(outputPath.empty() || outputPath == existing);
    return true;
  }
  return false;
}

static llvm::SmallString<128> computeAuxiliaryOutputPath(
    Compilation &C, CommandOutput &output, file_types::ID outputType,
    const TypeToPathMap *outputMap, StringRef workingDirectory,
    StringRef outputPath = StringRef(),
    llvm::opt::OptSpecifier requireArg = llvm::opt::OptSpecifier()) {

  if (hasExistingAdditionalOutput(output, outputType, outputPath))
    return {};

  if (outputMap) {
    auto iter = outputMap->find(outputType);
    if (iter != outputMap->end()) {
      StringRef outputMapPath = iter->second;
      // Prefer a path from the OutputMap.
      if (!outputMapPath.empty())
        return outputMapPath;
    }
  }
  if (!outputPath.empty())
    return outputPath;

  if (requireArg.isValid() && !C.getArgs().getLastArg(requireArg)) {
    // This auxiliary output only exists if requireArg is passed, but it
    // wasn't this time.
    return {};
  }

  // Put the auxiliary output file next to "the" primary output file.
  //
  // FIXME: when we're in WMO and have multiple primary outputs, we derive the
  // additional filename here from the _first_ primary output name, which
  // means that in the derived OFM (in Job.cpp) the additional output will
  // have a possibly-surprising name. But that's only half the problem: it
  // also get associated with the first primary _input_, even when there are
  // multiple primary inputs; really it should be associated with the build as
  // a whole -- derived OFM input "" -- but that's a more general thing to
  // fix.
  llvm::SmallString<128> path;
  if (output.getPrimaryOutputType() != file_types::TY_Nothing)
    path = output.getPrimaryOutputFilenames()[0];
  else if (!output.getBaseInput(0).empty())
    path = llvm::sys::path::filename(output.getBaseInput(0));
  else {
    formFilenameFromBaseAndExt(C.getOutputInfo().ModuleName, /*newExt=*/"",
                               workingDirectory, path);
  }
  assert(!path.empty());

  const bool isTempFile = C.isTemporaryFile(path);
  llvm::sys::path::replace_extension(path,
                                     file_types::getExtension(outputType));
  if (isTempFile)
    C.addTemporaryFile(path);
  return path;
}

static void addAuxiliaryOutput(
    Compilation &C, CommandOutput &output, file_types::ID outputType,
    const TypeToPathMap *outputMap, StringRef workingDirectory,
    StringRef outputPath = StringRef(),
    llvm::opt::OptSpecifier requireArg = llvm::opt::OptSpecifier()) {

  const auto path =
      computeAuxiliaryOutputPath(C, output, outputType, outputMap,
                                 workingDirectory, outputPath, requireArg);
  if (path.empty())
    return;
  output.setAdditionalOutputForType(outputType, path);
}

static void addDiagFileOutputForPersistentPCHAction(
    Compilation &C, const GeneratePCHJobAction *JA, CommandOutput &output,
    const TypeToPathMap *outputMap, StringRef workingDirectory) {
  assert(JA->isPersistentPCH());

  // For a persistent PCH we don't use an output, the frontend determines
  // the filename to use for the PCH. For the diagnostics file, try to
  // determine an invocation-specific path inside the directory where the
  // PCH is going to be written, and fallback to a temporary file if we
  // cannot determine such a path.

  StringRef pchOutDir = JA->getPersistentPCHDir();
  StringRef headerPath = output.getBaseInput(JA->getInputIndex());
  StringRef stem = llvm::sys::path::stem(headerPath);
  StringRef suffix =
      file_types::getExtension(file_types::TY_SerializedDiagnostics);
  SmallString<256> outPathBuf;

  if (const Arg *A = C.getArgs().getLastArg(options::OPT_emit_module_path)) {
    // The module file path is unique for a specific module and architecture
    // (it won't be concurrently written to) so we can use the path as hash
    // for determining the filename to use for the diagnostic file.
    StringRef ModuleOutPath = A->getValue();
    outPathBuf = pchOutDir;
    llvm::sys::path::append(outPathBuf, stem);
    outPathBuf += '-';
    auto code = llvm::hash_value(ModuleOutPath);
    outPathBuf += llvm::APInt(64, code).toString(36, /*Signed=*/false);
    llvm::sys::path::replace_extension(outPathBuf, suffix);
  }

  if (outPathBuf.empty()) {
    // Fallback to creating a temporary file.
    std::error_code EC =
    llvm::sys::fs::createTemporaryFile(stem, suffix, outPathBuf);
    if (EC) {
      C.getDiags().diagnose(SourceLoc(),
                            diag::error_unable_to_make_temporary_file,
                            EC.message());
      return;
    }
    C.addTemporaryFile(outPathBuf.str());
  }

  if (!outPathBuf.empty()) {
    addAuxiliaryOutput(C, output, file_types::TY_SerializedDiagnostics,
                       outputMap, workingDirectory, outPathBuf.str());
  }
}

/// If the file at \p input has not been modified since the last build (i.e. its
/// mtime has not changed), adjust the Job's condition accordingly.
static void handleCompileJobCondition(Job *J,
                                      CompileJobAction::InputInfo inputInfo,
                                      Optional<StringRef> input,
                                      bool alwaysRebuildDependents) {
  using InputStatus = CompileJobAction::InputInfo::Status;

  if (inputInfo.status == InputStatus::NewlyAdded) {
    J->setCondition(Job::Condition::NewlyAdded);
    return;
  }

  auto output = J->getOutput().getPrimaryOutputFilename();
  bool hasValidModTime = false;
  llvm::sys::fs::file_status inputStatus;
  if (input.hasValue() && !llvm::sys::fs::status(*input, inputStatus)) {
    J->setInputModTime(inputStatus.getLastModificationTime());
    hasValidModTime = J->getInputModTime() == inputInfo.previousModTime;
  } else if (!llvm::sys::fs::status(output, inputStatus)) {
    J->setInputModTime(inputStatus.getLastModificationTime());
    hasValidModTime = true;
  }

  Job::Condition condition;
  if (hasValidModTime) {
    switch (inputInfo.status) {
    case InputStatus::UpToDate:
      if (llvm::sys::fs::exists(output))
        condition = Job::Condition::CheckDependencies;
      else
        condition = Job::Condition::RunWithoutCascading;
      break;
    case InputStatus::NeedsCascadingBuild:
      condition = Job::Condition::Always;
      break;
    case InputStatus::NeedsNonCascadingBuild:
      condition = Job::Condition::RunWithoutCascading;
      break;
    case InputStatus::NewlyAdded:
      llvm_unreachable("handled above");
    }
  } else {
    if (alwaysRebuildDependents ||
        inputInfo.status == InputStatus::NeedsCascadingBuild) {
      condition = Job::Condition::Always;
    } else {
      condition = Job::Condition::RunWithoutCascading;
    }
  }

  J->setCondition(condition);
}

Job *Driver::buildJobsForAction(Compilation &C, const JobAction *JA,
                                const OutputFileMap *OFM,
                                StringRef workingDirectory,
                                bool AtTopLevel, JobCacheMap &JobCache) const {

  PrettyStackTraceDriverAction CrashInfo("building jobs", JA);

  // 1. See if we've already got this cached.
  const ToolChain &TC = C.getToolChain();
  std::pair<const Action *, const ToolChain *> Key(JA, &TC);
  {
    auto CacheIter = JobCache.find(Key);
    if (CacheIter != JobCache.end()) {
      return CacheIter->second;
    }
  }

  // 2. Build up the list of input jobs.
  SmallVector<const Action *, 4> InputActions;
  SmallVector<const Job *, 4> InputJobs;
  for (const Action *Input : *JA) {
    if (auto *InputJobAction = dyn_cast<JobAction>(Input)) {
      InputJobs.push_back(buildJobsForAction(
          C, InputJobAction, OFM, workingDirectory, false, JobCache));
    } else {
      InputActions.push_back(Input);
    }
  }

  // 3. Determine the CommandOutput for the job.
  StringRef BaseInput;
  StringRef PrimaryInput;
  if (!InputActions.empty()) {
    // Use the first InputAction as our BaseInput and PrimaryInput.
    const InputAction *IA = cast<InputAction>(InputActions[0]);
    BaseInput = IA->getInputArg().getValue();
    PrimaryInput = BaseInput;
  } else if (!InputJobs.empty()) {
    const CommandOutput &Out = InputJobs.front()->getOutput();
    size_t i = JA->getInputIndex();
    // Use the first Job's BaseInput as our BaseInput.
    BaseInput = Out.getBaseInput(i);
    // Use the first Job's Primary Output as our PrimaryInput.
    PrimaryInput = Out.getPrimaryOutputFilenames()[i];
  }

  // With -index-file option, the primary input is the one passed with
  // -index-file-path.
  // FIXME: Figure out how this better fits within the driver infrastructure.
  if (JA->getType() == file_types::TY_IndexData) {
    if (Arg *A = C.getArgs().getLastArg(options::OPT_index_file_path)) {
      BaseInput = A->getValue();
      PrimaryInput = A->getValue();
    }
  }

  const OutputInfo &OI = C.getOutputInfo();
  const TypeToPathMap *OutputMap = nullptr;
  if (OFM) {
    if (isa<CompileJobAction>(JA)) {
      if (OI.CompilerMode == OutputInfo::Mode::SingleCompile) {
        OutputMap = OFM->getOutputMapForSingleOutput();
      } else {
        OutputMap = OFM->getOutputMapForInput(BaseInput);
      }
    } else if (isa<BackendJobAction>(JA)) {
      OutputMap = OFM->getOutputMapForInput(BaseInput);
    }
  }

  std::unique_ptr<CommandOutput> Output(
      new CommandOutput(JA->getType(), C.getDerivedOutputFileMap()));

  PrettyStackTraceDriverCommandOutput CrashInfo2("determining output",
                                                 Output.get());
  llvm::SmallString<128> Buf;
  computeMainOutput(C, JA, OFM, AtTopLevel, InputActions, InputJobs, OutputMap,
                    workingDirectory, BaseInput, PrimaryInput, Buf,
                    Output.get());

  if (OI.ShouldGenerateModule && isa<CompileJobAction>(JA))
    chooseSwiftModuleOutputPath(C, OutputMap, workingDirectory, Output.get());

  if (OI.ShouldGenerateModule &&
      (isa<CompileJobAction>(JA) || isa<MergeModuleJobAction>(JA))) {
    chooseSwiftModuleDocOutputPath(C, OutputMap, workingDirectory, Output.get());
    if (!C.getArgs().hasArg(options::OPT_avoid_emit_module_source_info)) {
      chooseSwiftSourceInfoOutputPath(C, OutputMap, workingDirectory,
                                      Output.get());
    }
  }

  if (C.getArgs().hasArg(options::OPT_emit_module_interface,
                         options::OPT_emit_module_interface_path))
    chooseModuleInterfacePath(C, JA, workingDirectory, Buf,
      file_types::TY_SwiftModuleInterfaceFile, Output.get());

  if (C.getArgs().hasArg(options::OPT_emit_private_module_interface_path))
    chooseModuleInterfacePath(C, JA, workingDirectory, Buf,
      file_types::TY_PrivateSwiftModuleInterfaceFile, Output.get());

  if (C.getArgs().hasArg(options::OPT_update_code) && isa<CompileJobAction>(JA))
    chooseRemappingOutputPath(C, OutputMap, Output.get());

  if (isa<CompileJobAction>(JA) || isa<GeneratePCHJobAction>(JA)) {
    // Choose the serialized diagnostics output path.
    if (C.getArgs().hasArg(options::OPT_serialize_diagnostics))
      chooseSerializedDiagnosticsPath(C, JA, OutputMap, workingDirectory,
                                      Output.get());
  }

  if (isa<CompileJobAction>(JA)) {
    chooseModuleSummaryPath(C, OutputMap, workingDirectory, Buf, Output.get());
  }

  if (isa<MergeModuleJobAction>(JA) ||
      (isa<CompileJobAction>(JA) &&
       OI.CompilerMode == OutputInfo::Mode::SingleCompile)) {
    // An emit-tbd argument gets passed down to a job that sees the whole
    // module, either the -merge-modules job or a -wmo compiler invocation.
    chooseTBDPath(C, OutputMap, workingDirectory, Buf, Output.get());
  }

  if (isa<CompileJobAction>(JA))
    chooseDependenciesOutputPaths(C, OutputMap, workingDirectory, Buf,
                                  Output.get());

  if (C.getArgs().hasArg(options::OPT_save_optimization_record,
                         options::OPT_save_optimization_record_EQ,
                         options::OPT_save_optimization_record_path))
    chooseOptimizationRecordPath(C, workingDirectory, Buf, Output.get());

  if ((isa<MergeModuleJobAction>(JA) ||
       (isa<CompileJobAction>(JA) &&
        OI.CompilerMode == OutputInfo::Mode::SingleCompile)) &&
      C.getArgs().hasArg(options::OPT_emit_objc_header,
                         options::OPT_emit_objc_header_path))
    chooseObjectiveCHeaderOutputPath(C, OutputMap, workingDirectory,
                                     Output.get());

  // 4. Construct a Job which produces the right CommandOutput.
  std::unique_ptr<Job> ownedJob = TC.constructJob(*JA, C, std::move(InputJobs),
                                                  InputActions, 
                                                  std::move(Output), OI);
  Job *J = C.addJob(std::move(ownedJob));

  // If we track dependencies for this job, we may be able to avoid running it.
  if (auto incrementalJob = dyn_cast<IncrementalJobAction>(JA)) {
    const bool alwaysRebuildDependents =
        C.getArgs().hasArg(options::OPT_driver_always_rebuild_dependents);
    if (!J->getOutput()
             .getAdditionalOutputForType(file_types::TY_SwiftDeps)
             .empty()) {
      if (InputActions.size() == 1) {
        handleCompileJobCondition(J, incrementalJob->getInputInfo(), BaseInput,
                                  alwaysRebuildDependents);
      }
    } else if (isa<MergeModuleJobAction>(JA)) {
      handleCompileJobCondition(J, incrementalJob->getInputInfo(), None,
                                alwaysRebuildDependents);
    }
  }

  // 5. Add it to the JobCache, so we don't construct the same Job multiple
  // times.
  JobCache[Key] = J;

  if (DriverPrintBindings) {
    llvm::outs() << "# \"" << TC.getTriple().str()
      << "\" - \"" << llvm::sys::path::filename(J->getExecutable())
      << "\", inputs: [";

    llvm::interleave(
        InputActions.begin(), InputActions.end(),
        [](const Action *A) {
          auto Input = cast<InputAction>(A);
          llvm::outs() << '"' << Input->getInputArg().getValue() << '"';
        },
        [] { llvm::outs() << ", "; });
    if (!InputActions.empty() && !J->getInputs().empty())
      llvm::outs() << ", ";
    llvm::interleave(
        J->getInputs().begin(), J->getInputs().end(),
        [](const Job *Input) {
          auto FileNames = Input->getOutput().getPrimaryOutputFilenames();
          interleave(
              FileNames.begin(), FileNames.end(),
              [](StringRef FileName) {
                llvm::outs() << '"' << FileName << '"';
              },
              [] { llvm::outs() << ", "; });
        },
        [] { llvm::outs() << ", "; });

    llvm::outs() << "], output: {";
    auto OutputFileNames = J->getOutput().getPrimaryOutputFilenames();
    StringRef TypeName =
        file_types::getTypeName(J->getOutput().getPrimaryOutputType());
    interleave(
        OutputFileNames.begin(), OutputFileNames.end(),
        [TypeName](StringRef FileName) {
          llvm::outs() << TypeName << ": \"" << FileName << '"';
        },
        [] { llvm::outs() << ", "; });

    file_types::forAllTypes([&J](file_types::ID Ty) {
      StringRef AdditionalOutput =
        J->getOutput().getAdditionalOutputForType(Ty);
      if (!AdditionalOutput.empty()) {
        llvm::outs() << ", " << file_types::getTypeName(Ty) << ": \""
                     << AdditionalOutput << '"';
      }
    });
    llvm::outs() << '}';

    switch (J->getCondition()) {
    case Job::Condition::Always:
      break;
    case Job::Condition::RunWithoutCascading:
      llvm::outs() << ", condition: run-without-cascading";
      break;
    case Job::Condition::CheckDependencies:
      llvm::outs() << ", condition: check-dependencies";
      break;
    case Job::Condition::NewlyAdded:
      llvm::outs() << ", condition: newly-added";
      break;
    }

    llvm::outs() << '\n';
  }

  return J;
}

void Driver::computeMainOutput(
    Compilation &C, const JobAction *JA, const OutputFileMap *OFM,
    bool AtTopLevel, SmallVectorImpl<const Action *> &InputActions,
    SmallVectorImpl<const Job *> &InputJobs, const TypeToPathMap *OutputMap,
    StringRef workingDirectory, StringRef BaseInput, StringRef PrimaryInput,
    llvm::SmallString<128> &Buf, CommandOutput *Output) const {
  StringRef OutputFile;
  if (C.getOutputInfo().isMultiThreading() && isa<CompileJobAction>(JA) &&
      file_types::isAfterLLVM(JA->getType())) {
    // Multi-threaded compilation: A single frontend command produces multiple
    // output file: one for each input files.

    // In batch mode, the driver will try to reserve multiple differing main
    // outputs to a bridging header. Another assertion will trip, but the cause
    // will be harder to track down. Since the driver now ignores -num-threads
    // in batch mode, the user should never be able to falsify this assertion.
    assert(!C.getBatchModeEnabled() && "Batch mode produces only one main "
                                       "output per input action, cannot have "
                                       "batch mode & num-threads");

    auto OutputFunc = [&](StringRef Base, StringRef Primary) {
      const TypeToPathMap *OMForInput = nullptr;
      if (OFM)
        OMForInput = OFM->getOutputMapForInput(Base);

      OutputFile = getOutputFilename(C, JA, OMForInput, workingDirectory,
                                     AtTopLevel, Base, Primary, Buf);
      Output->addPrimaryOutput(CommandInputPair(Base, Primary),
                               OutputFile);
    };
    // Add an output file for each input action.
    for (const Action *A : InputActions) {
      const InputAction *IA = cast<InputAction>(A);
      StringRef IV = IA->getInputArg().getValue();
      OutputFunc(IV, IV);
    }
    // Add an output file for each primary output of each input job.
    for (const Job *IJ : InputJobs) {
      size_t i = 0;
      CommandOutput const &Out = IJ->getOutput();
      for (auto OutPrimary : Out.getPrimaryOutputFilenames()) {
        OutputFunc(Out.getBaseInput(i++), OutPrimary);
      }
    }
  } else {
    // The common case: there is a single output file.
    OutputFile = getOutputFilename(C, JA, OutputMap, workingDirectory,
                                   AtTopLevel, BaseInput, PrimaryInput, Buf);
    Output->addPrimaryOutput(CommandInputPair(BaseInput, PrimaryInput),
                             OutputFile);
  }
}

void Driver::chooseSwiftModuleOutputPath(Compilation &C,
                                         const TypeToPathMap *OutputMap,
                                         StringRef workingDirectory,
                                         CommandOutput *Output) const {

  if (hasExistingAdditionalOutput(*Output, file_types::TY_SwiftModuleFile))
    return;

  StringRef OFMModuleOutputPath;
  if (OutputMap) {
    auto iter = OutputMap->find(file_types::TY_SwiftModuleFile);
    if (iter != OutputMap->end())
      OFMModuleOutputPath = iter->second;
  }

  const OutputInfo &OI = C.getOutputInfo();
  const Arg *A = C.getArgs().getLastArg(options::OPT_emit_module_path);
  using file_types::TY_SwiftModuleFile;

  if (!OFMModuleOutputPath.empty()) {
    // Prefer a path from the OutputMap.
    Output->setAdditionalOutputForType(TY_SwiftModuleFile, OFMModuleOutputPath);
  } else if (A && OI.CompilerMode == OutputInfo::Mode::SingleCompile) {
    // We're performing a single compilation (and thus no merge module step),
    // so prefer to use -emit-module-path, if present.
    Output->setAdditionalOutputForType(TY_SwiftModuleFile, A->getValue());
  } else if (Output->getPrimaryOutputType() == TY_SwiftModuleFile) {
    // If the primary type is already a module type, we're out of
    // options for overriding the primary name choice: stop now.
    assert(!Output->getPrimaryOutputFilename().empty());
    return;
  } else if (OI.CompilerMode == OutputInfo::Mode::SingleCompile &&
             OI.ShouldTreatModuleAsTopLevelOutput) {
    // We're performing a single compile and don't have -emit-module-path,
    // but have been told to treat the module as a top-level output.
    // Determine an appropriate path.
    llvm::SmallString<128> Path;
    if (const Arg *A = C.getArgs().getLastArg(options::OPT_o)) {
      // Put the module next to the top-level output.
      Path = A->getValue();
      llvm::sys::path::remove_filename(Path);
    } else {
      // A top-level output wasn't specified, so just output to
      // <ModuleName>.swiftmodule in the current directory.
    }
    llvm::sys::path::append(Path, OI.ModuleName);
    llvm::sys::path::replace_extension(
        Path, file_types::getExtension(TY_SwiftModuleFile));
    Output->setAdditionalOutputForType(TY_SwiftModuleFile, Path);
  } else if (Output->getPrimaryOutputType() != file_types::TY_Nothing) {
    // We're only generating the module as an intermediate, so put it next
    // to the primary output of the compile command.
    llvm::SmallString<128> Path(Output->getPrimaryOutputFilenames()[0]);
    assert(!Path.empty());
    bool isTempFile = C.isTemporaryFile(Path);
    llvm::sys::path::replace_extension(
        Path, file_types::getExtension(TY_SwiftModuleFile));
    Output->setAdditionalOutputForType(TY_SwiftModuleFile, Path);
    if (isTempFile)
      C.addTemporaryFile(Path);
  }
}

static void chooseModuleAuxiliaryOutputFilePath(Compilation &C,
                                                const TypeToPathMap *OutputMap,
                                                StringRef workingDirectory,
                                                CommandOutput *Output,
                                                file_types::ID fileID,
                                                bool shouldUseProjectFolder = false,
                                                Optional<options::ID> optId = llvm::None) {
  if (hasExistingAdditionalOutput(*Output, fileID))
    return;
  // Honor driver option for this path if it's given
  if (optId.hasValue()) {
    if (const Arg *A = C.getArgs().getLastArg(*optId)) {
      Output->setAdditionalOutputForType(fileID, StringRef(A->getValue()));
      return;
    }
  }

  StringRef OFMOutputPath;
  if (OutputMap) {
    auto iter = OutputMap->find(fileID);
    if (iter != OutputMap->end())
      OFMOutputPath = iter->second;
  }
  if (!OFMOutputPath.empty()) {
    // Prefer a path from the OutputMap.
    Output->setAdditionalOutputForType(fileID, OFMOutputPath);
  } else if (Output->getPrimaryOutputType() != file_types::TY_Nothing) {
    auto ModulePath = Output->getAnyOutputForType(file_types::TY_SwiftModuleFile);
    bool isTempFile = C.isTemporaryFile(ModulePath);
    auto ModuleName = llvm::sys::path::filename(ModulePath);
    llvm::SmallString<128> Path(llvm::sys::path::parent_path(ModulePath));
    if (shouldUseProjectFolder) {
      llvm::sys::path::append(Path, "Project");
      // If the build system has created a Project dir for us to include the file, use it.
      if (!llvm::sys::fs::exists(Path)) {
        llvm::sys::path::remove_filename(Path);
      }
    }
    llvm::sys::path::append(Path, ModuleName);
    llvm::sys::path::replace_extension(Path, file_types::getExtension(fileID));
    Output->setAdditionalOutputForType(fileID, Path);
    if (isTempFile)
      C.addTemporaryFile(Path);
  }
}

void Driver::chooseSwiftSourceInfoOutputPath(Compilation &C,
                                             const TypeToPathMap *OutputMap,
                                             StringRef workingDirectory,
                                             CommandOutput *Output) const {
  chooseModuleAuxiliaryOutputFilePath(C, OutputMap, workingDirectory, Output,
                                      file_types::TY_SwiftSourceInfoFile,
                                      /*shouldUseProjectFolder*/true,
                                      options::OPT_emit_module_source_info_path);
}

void Driver::chooseSwiftModuleDocOutputPath(Compilation &C,
                                            const TypeToPathMap *OutputMap,
                                            StringRef workingDirectory,
                                            CommandOutput *Output) const {
  chooseModuleAuxiliaryOutputFilePath(C, OutputMap, workingDirectory, Output,
                                      file_types::TY_SwiftModuleDocFile);
}

void Driver::chooseRemappingOutputPath(Compilation &C,
                                       const TypeToPathMap *OutputMap,
                                       CommandOutput *Output) const {

  if (hasExistingAdditionalOutput(*Output, file_types::TY_Remapping))
    return;

  StringRef OFMFixitsOutputPath;
  if (OutputMap) {
    auto iter = OutputMap->find(file_types::TY_Remapping);
    if (iter != OutputMap->end())
      OFMFixitsOutputPath = iter->second;
  }
  if (!OFMFixitsOutputPath.empty()) {
    Output->setAdditionalOutputForType(file_types::ID::TY_Remapping,
                                       OFMFixitsOutputPath);
  } else {
    llvm::SmallString<128> Path(Output->getPrimaryOutputFilenames()[0]);
    bool isTempFile = C.isTemporaryFile(Path);
    llvm::sys::path::replace_extension(Path,
        file_types::getExtension(file_types::ID::TY_Remapping));
    Output->setAdditionalOutputForType(file_types::ID::TY_Remapping, Path);
    if (isTempFile)
      C.addTemporaryFile(Path);
  }
}

void Driver::chooseModuleInterfacePath(Compilation &C, const JobAction *JA,
                                       StringRef workingDirectory,
                                       llvm::SmallString<128> &buffer,
                                       file_types::ID fileType,
                                       CommandOutput *output) const {
  switch (C.getOutputInfo().CompilerMode) {
  case OutputInfo::Mode::StandardCompile:
  case OutputInfo::Mode::BatchModeCompile:
    if (!isa<MergeModuleJobAction>(JA))
      return;
    break;
  case OutputInfo::Mode::SingleCompile:
    if (!isa<CompileJobAction>(JA))
      return;
    break;
  case OutputInfo::Mode::Immediate:
  case OutputInfo::Mode::REPL:
    llvm_unreachable("these modes aren't usable with 'swiftc'");
  }

  auto pathOpt = fileType == file_types::TY_SwiftModuleInterfaceFile?
    options::OPT_emit_module_interface_path:
    options::OPT_emit_private_module_interface_path;

  StringRef outputPath = *getOutputFilenameFromPathArgOrAsTopLevel(
      C.getOutputInfo(), C.getArgs(), pathOpt, fileType,
      /*TreatAsTopLevelOutput*/true, workingDirectory, buffer);
  output->setAdditionalOutputForType(fileType, outputPath);
}

void Driver::chooseModuleSummaryPath(Compilation &C,
                                     const TypeToPathMap *OutputMap,
                                     StringRef workingDirectory,
                                     llvm::SmallString<128> &Buf,
                                     CommandOutput *Output) const {
  StringRef pathFromArgs;
  if (const Arg *A =
          C.getArgs().getLastArg(options::OPT_emit_module_summary_path)) {
    pathFromArgs = A->getValue();
  }

  addAuxiliaryOutput(C, *Output, file_types::TY_SwiftModuleSummaryFile,
                     OutputMap, workingDirectory, pathFromArgs,
                     /*requireArg=*/options::OPT_emit_module_summary);
}

void Driver::chooseSerializedDiagnosticsPath(Compilation &C,
                                             const JobAction *JA,
                                             const TypeToPathMap *OutputMap,
                                             StringRef workingDirectory,
                                             CommandOutput *Output) const {
  if (C.getArgs().hasArg(options::OPT_serialize_diagnostics)) {
    auto pchJA = dyn_cast<GeneratePCHJobAction>(JA);
    if (pchJA && pchJA->isPersistentPCH()) {
      addDiagFileOutputForPersistentPCHAction(C, pchJA, *Output, OutputMap,
                                              workingDirectory);
    } else {
      addAuxiliaryOutput(C, *Output, file_types::TY_SerializedDiagnostics,
                         OutputMap, workingDirectory);
    }

    // Remove any existing diagnostics files so that clients can detect their
    // presence to determine if a command was run.
    StringRef OutputPath =
        Output->getAnyOutputForType(file_types::TY_SerializedDiagnostics);
    if (llvm::sys::fs::is_regular_file(OutputPath))
      llvm::sys::fs::remove(OutputPath);
  }
}

void Driver::chooseDependenciesOutputPaths(Compilation &C,
                                           const TypeToPathMap *OutputMap,
                                           StringRef workingDirectory,
                                           llvm::SmallString<128> &Buf,
                                           CommandOutput *Output) const {
  if (C.getArgs().hasArg(options::OPT_emit_dependencies)) {
    auto depPath = computeAuxiliaryOutputPath(
        C, *Output, file_types::TY_Dependencies, OutputMap, workingDirectory);
    C.addDependencyPathOrCreateDummy(depPath, [&] {
      addAuxiliaryOutput(C, *Output, file_types::TY_Dependencies, OutputMap,
                         workingDirectory);
    });
  }
  if (C.getIncrementalBuildEnabled()) {
    file_types::forEachIncrementalOutputType([&](file_types::ID type) {
      if (C.getEnableSourceRangeDependencies() || C.IncrementalComparator ||
          type == file_types::TY_SwiftDeps)
        addAuxiliaryOutput(C, *Output, type, OutputMap, workingDirectory);
    });
  }
  chooseLoadedModuleTracePath(C, workingDirectory, Buf, Output);
}

void Driver::chooseLoadedModuleTracePath(Compilation &C,
                                         StringRef workingDirectory,
                                         llvm::SmallString<128> &Buf,
                                         CommandOutput *Output) const {
  // The loaded-module-trace is the same for all compile jobs: all `import`
  // statements are processed, even ones from non-primary files. Thus, only
  // one of those jobs needs to emit the file, and we can get it to write
  // straight to the desired final location.
  auto tracePathEnvVar = getenv("SWIFT_LOADED_MODULE_TRACE_FILE");
  auto shouldEmitTrace =
      tracePathEnvVar ||
      C.getArgs().hasArg(options::OPT_emit_loaded_module_trace,
                         options::OPT_emit_loaded_module_trace_path);

  if (shouldEmitTrace &&
      C.requestPermissionForFrontendToEmitLoadedModuleTrace()) {
    StringRef filename;
    // Prefer the environment variable.
    if (tracePathEnvVar)
      filename = StringRef(tracePathEnvVar);
    else {
      // By treating this as a top-level output, the return value always
      // exists.
      filename = *getOutputFilenameFromPathArgOrAsTopLevel(
          C.getOutputInfo(), C.getArgs(),
          options::OPT_emit_loaded_module_trace_path,
          file_types::TY_ModuleTrace,
          /*TreatAsTopLevelOutput=*/true, workingDirectory, Buf);
    }

    Output->setAdditionalOutputForType(file_types::TY_ModuleTrace, filename);
  }
}

void Driver::chooseTBDPath(Compilation &C, const TypeToPathMap *OutputMap,
                           StringRef workingDirectory,
                           llvm::SmallString<128> &Buf,
                           CommandOutput *Output) const {
  StringRef pathFromArgs;
  if (const Arg *A = C.getArgs().getLastArg(options::OPT_emit_tbd_path)) {
    pathFromArgs = A->getValue();
  }

  addAuxiliaryOutput(C, *Output, file_types::TY_TBD, OutputMap,
                     workingDirectory, pathFromArgs,
                     /*requireArg=*/options::OPT_emit_tbd);
}

void Driver::chooseOptimizationRecordPath(Compilation &C,
                                          StringRef workingDirectory,
                                          llvm::SmallString<128> &Buf,
                                          CommandOutput *Output) const {
  const OutputInfo &OI = C.getOutputInfo();
  if (OI.CompilerMode == OutputInfo::Mode::SingleCompile) {
    llvm::Expected<file_types::ID> FileType =
        C.getToolChain().remarkFileTypeFromArgs(C.getArgs());
    if (!FileType) {
      Diags.diagnose({}, diag::error_creating_remark_serializer,
                     llvm::toString(FileType.takeError()));
      return;
    }
    auto filename = *getOutputFilenameFromPathArgOrAsTopLevel(
        OI, C.getArgs(), options::OPT_save_optimization_record_path, *FileType,
        /*TreatAsTopLevelOutput=*/true, workingDirectory, Buf);

    Output->setAdditionalOutputForType(*FileType, filename);
  } else
    // FIXME: We should use the OutputMap in this case.
    Diags.diagnose({}, diag::warn_opt_remark_disabled);
}

void Driver::chooseObjectiveCHeaderOutputPath(Compilation &C,
                                              const TypeToPathMap *OutputMap,
                                              StringRef workingDirectory,
                                              CommandOutput *Output) const {

  if (hasExistingAdditionalOutput(*Output, file_types::TY_ObjCHeader))
    return;

  StringRef ObjCHeaderPath;
  if (OutputMap) {
    auto iter = OutputMap->find(file_types::TY_ObjCHeader);
    if (iter != OutputMap->end())
      ObjCHeaderPath = iter->second;
  }

  if (ObjCHeaderPath.empty())
    if (auto A = C.getArgs().getLastArg(options::OPT_emit_objc_header_path))
      ObjCHeaderPath = A->getValue();

  if (!ObjCHeaderPath.empty()) {
    Output->setAdditionalOutputForType(file_types::TY_ObjCHeader,
                                       ObjCHeaderPath);
  } else {
    // Put the header next to the primary output file.
    // FIXME: That's not correct if the user /just/ passed -emit-header
    // and not -emit-module.
    addAuxiliaryOutput(C, *Output, file_types::TY_ObjCHeader,
                       /*output file map*/ nullptr, workingDirectory);
  }
}

static unsigned printActions(const Action *A,
                             llvm::DenseMap<const Action *, unsigned> &Ids) {
  if (Ids.count(A))
    return Ids[A];

  std::string str;
  llvm::raw_string_ostream os(str);

  os << Action::getClassName(A->getKind()) << ", ";
  if (const auto *IA = dyn_cast<InputAction>(A)) {
    os << "\"" << IA->getInputArg().getValue() << "\"";
  } else {
    os << "{";
    llvm::interleave(
        *cast<JobAction>(A),
        [&](const Action *Input) { os << printActions(Input, Ids); },
        [&] { os << ", "; });
    os << "}";
  }

  unsigned Id = Ids.size();
  Ids[A] = Id;
  llvm::errs() << Id << ": " << os.str() << ", "
               << file_types::getTypeName(A->getType()) << "\n";

  return Id;
}

void Driver::printActions(const Compilation &C) const {
  llvm::DenseMap<const Action *, unsigned> Ids;
  for (const Action *A : C.getActions()) {
    ::printActions(A, Ids);
  }
}

void Driver::printVersion(const ToolChain &TC, raw_ostream &OS) const {
  OS << version::getSwiftFullVersion(
    version::Version::getCurrentLanguageVersion()) << '\n';
  OS << "Target: " << TC.getTriple().str() << '\n';
}

void Driver::printHelp(bool ShowHidden) const {
  unsigned IncludedFlagsBitmask = 0;
  unsigned ExcludedFlagsBitmask = options::NoDriverOption;

  switch (driverKind) {
  case DriverKind::Interactive:
    ExcludedFlagsBitmask |= options::NoInteractiveOption;
    break;
  case DriverKind::Batch:
  case DriverKind::AutolinkExtract:
  case DriverKind::SwiftIndent:
  case DriverKind::SymbolGraph:
    ExcludedFlagsBitmask |= options::NoBatchOption;
    break;
  }

  if (!ShowHidden)
    ExcludedFlagsBitmask |= HelpHidden;

  getOpts().PrintHelp(llvm::outs(), Name.c_str(), "Swift compiler",
                      IncludedFlagsBitmask, ExcludedFlagsBitmask,
                      /*ShowAllAliases*/false);

  // These strings match the descriptions found in the corresponding swiftpm 
  // help pages
  if (driverKind == DriverKind::Interactive) {
    llvm::outs() << "\nSEE ALSO - PACKAGE MANAGER COMMANDS: \n"
        "\t\"swift build\" Build sources into binary products \n"
        "\t\"swift package\" Perform operations on Swift packages \n"
        "\t\"swift run\" Build and run an executable product \n"
        "\t\"swift test\" Build and run tests \n";
  } else {
    llvm::outs() << "\nSEE ALSO: swift build, swift run, swift package, " 
                    "swift test \n";
  }

}

bool OutputInfo::mightHaveExplicitPrimaryInputs(
    const CommandOutput &Output) const {
  switch (CompilerMode) {
  case Mode::StandardCompile:
  case Mode::BatchModeCompile:
    return true;
  case Mode::SingleCompile:
    return false;
  case Mode::Immediate:
  case Mode::REPL:
    llvm_unreachable("REPL and immediate modes handled elsewhere");
  }
  llvm_unreachable("unhandled mode");
}
