//===-- ParseableInterfaceModuleLoader.cpp - Loads .swiftinterface files --===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2019 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
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "textual-module-interface"
#include "swift/Frontend/ParseableInterfaceModuleLoader.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/AST/DiagnosticsSema.h"
#include "swift/AST/FileSystem.h"
#include "swift/AST/Module.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/Basic/Lazy.h"
#include "swift/Basic/STLExtras.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/ParseableInterfaceSupport.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/Serialization/ModuleFormat.h"
#include "swift/Serialization/SerializationOptions.h"
#include "swift/Serialization/Validation.h"
#include "clang/Basic/Module.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Frontend/CompilerInstance.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/xxhash.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/YAMLTraits.h"

using namespace swift;
using FileDependency = SerializationOptions::FileDependency;

/// Extract the specified-or-defaulted -module-cache-path that winds up in
/// the clang importer, for reuse as the .swiftmodule cache path when
/// building a ParseableInterfaceModuleLoader.
std::string
swift::getModuleCachePathFromClang(const clang::CompilerInstance &Clang) {
  if (!Clang.hasPreprocessor())
    return "";
  std::string SpecificModuleCachePath = Clang.getPreprocessor()
    .getHeaderSearchInfo()
    .getModuleCachePath();

  // The returned-from-clang module cache path includes a suffix directory
  // that is specific to the clang version and invocation; we want the
  // directory above that.
  return llvm::sys::path::parent_path(SpecificModuleCachePath);
}

#pragma mark - Forwarding Modules

namespace {

/// Describes a "forwarding module", that is, a .swiftmodule that's actually
/// a YAML file inside, pointing to a the original .swiftmodule but describing
/// a different dependency resolution strategy.
struct ForwardingModule {
  /// The path to the original .swiftmodule in the prebuilt cache.
  std::string underlyingModulePath;

  /// Describes a set of file-based dependencies with their size and
  /// modification time stored. This is slightly different from
  /// \c SerializationOptions::FileDependency, because this type needs to be
  /// serializable to and from YAML.
  struct Dependency {
    std::string path;
    uint64_t size;
    uint64_t lastModificationTime;
  };
  std::vector<Dependency> dependencies;
  unsigned version = 1;

  ForwardingModule() = default;
  ForwardingModule(StringRef underlyingModulePath)
  : underlyingModulePath(underlyingModulePath) {}

  /// Loads the contents of the forwarding module whose contents lie in
  /// the provided buffer, and returns a new \c ForwardingModule, or an error
  /// if the YAML could not be parsed.
  static llvm::ErrorOr<ForwardingModule> load(const llvm::MemoryBuffer &buf);

  /// Adds a given dependency to the dependencies list.
  void addDependency(StringRef path, uint64_t size, uint64_t modTime) {
    dependencies.push_back({path.str(), size, modTime});
  }
};

} // end anonymous namespace

#pragma mark - YAML Serialization

namespace llvm {
  namespace yaml {
    template <>
    struct MappingTraits<ForwardingModule::Dependency> {
      static void mapping(IO &io, ForwardingModule::Dependency &dep) {
        io.mapRequired("mtime", dep.lastModificationTime);
        io.mapRequired("path", dep.path);
        io.mapRequired("size", dep.size);
      }
    };

    template <>
    struct SequenceElementTraits<ForwardingModule::Dependency> {
      static const bool flow = false;
    };

    template <>
    struct MappingTraits<ForwardingModule> {
      static void mapping(IO &io, ForwardingModule &module) {
        io.mapRequired("path", module.underlyingModulePath);
        io.mapRequired("dependencies", module.dependencies);
        io.mapRequired("version", module.version);
      }
    };
  }
} // end namespace llvm

llvm::ErrorOr<ForwardingModule>
ForwardingModule::load(const llvm::MemoryBuffer &buf) {
  llvm::yaml::Input yamlIn(buf.getBuffer());
  ForwardingModule fwd;
  yamlIn >> fwd;
  if (yamlIn.error())
    return yamlIn.error();

  // We only currently support Version 1 of the forwarding module format.
  if (fwd.version != 1)
    return std::make_error_code(std::errc::not_supported);
  return std::move(fwd);
}

#pragma mark - Module Discovery

namespace {

/// The result of a search for a module either alongside an interface, in the
/// module cache, or in the prebuilt module cache.
class DiscoveredModule {
  /// The kind of module we've found.
  enum class Kind {
    /// A module that's either alongside the swiftinterface or in the
    /// module cache.
    Normal,

    /// A module that resides in the prebuilt cache, and has hash-based
    /// dependencies.
    Prebuilt,

    /// A 'forwarded' module. This is a module in the prebuilt cache, but whose
    /// dependencies live in a forwarding module.
    /// \sa ForwardingModule.
    Forwarded
  };

  /// The kind of module that's been discovered.
  const Kind kind;

  DiscoveredModule(StringRef path, Kind kind,
    std::unique_ptr<llvm::MemoryBuffer> moduleBuffer)
    : kind(kind), moduleBuffer(std::move(moduleBuffer)), path(path) {}

public:
  /// The contents of the .swiftmodule, if we've read it while validating
  /// dependencies.
  std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;

  /// The path to the discovered serialized .swiftmodule on disk.
  const std::string path;

  /// Creates a \c Normal discovered module.
  static DiscoveredModule normal(StringRef path,
      std::unique_ptr<llvm::MemoryBuffer> moduleBuffer) {
    return { path, Kind::Normal, std::move(moduleBuffer) };
  }

  /// Creates a \c Prebuilt discovered module.
  static DiscoveredModule prebuilt(
      StringRef path, std::unique_ptr<llvm::MemoryBuffer> moduleBuffer) {
    return { path, Kind::Prebuilt, std::move(moduleBuffer) };
  }

  /// Creates a \c Forwarded discovered module, whose dependencies have been
  /// externally validated by a \c ForwardingModule.
  static DiscoveredModule forwarded(
      StringRef path, std::unique_ptr<llvm::MemoryBuffer> moduleBuffer) {
    return { path, Kind::Forwarded, std::move(moduleBuffer) };
  }

  bool isNormal() const { return kind == Kind::Normal; }
  bool isPrebuilt() const { return kind == Kind::Prebuilt; }
  bool isForwarded() const { return kind == Kind::Forwarded; }
};

} // end anonymous namespace

#pragma mark - Common utilities

namespace path = llvm::sys::path;

static bool serializedASTLooksValid(const llvm::MemoryBuffer &buf) {
  auto VI = serialization::validateSerializedAST(buf.getBuffer());
  return VI.status == serialization::Status::Valid;
}

static std::unique_ptr<llvm::MemoryBuffer> getBufferOfDependency(
  llvm::vfs::FileSystem &fs, StringRef depPath, StringRef interfacePath,
  DiagnosticEngine &diags, SourceLoc diagnosticLoc) {
  auto depBuf = fs.getBufferForFile(depPath, /*FileSize=*/-1,
                                    /*RequiresNullTerminator=*/false);
  if (!depBuf) {
    diags.diagnose(diagnosticLoc,
                   diag::missing_dependency_of_parseable_module_interface,
                   depPath, interfacePath, depBuf.getError().message());
    return nullptr;
  }
  return std::move(depBuf.get());
}

static Optional<llvm::vfs::Status> getStatusOfDependency(
  llvm::vfs::FileSystem &fs, StringRef depPath, StringRef interfacePath,
  DiagnosticEngine &diags, SourceLoc diagnosticLoc) {
  auto status = fs.status(depPath);
  if (!status) {
    diags.diagnose(diagnosticLoc,
                   diag::missing_dependency_of_parseable_module_interface,
                   depPath, interfacePath, status.getError().message());
    return None;
  }
  return status.get();
}

#pragma mark - Module Building

/// Builds a parseable module interface into a .swiftmodule at the provided
/// output path.
/// \note Needs to be in the swift namespace so CompilerInvocation can see it.
class swift::ParseableInterfaceBuilder {
  ASTContext &ctx;
  llvm::vfs::FileSystem &fs;
  DiagnosticEngine &diags;
  const StringRef interfacePath;
  const StringRef moduleName;
  const StringRef moduleCachePath;
  const StringRef prebuiltCachePath;
  const bool serializeDependencyHashes;
  const bool trackSystemDependencies;
  const SourceLoc diagnosticLoc;
  DependencyTracker *const dependencyTracker;
  CompilerInvocation subInvocation;

  void configureSubInvocationInputsAndOutputs(StringRef OutPath) {
    auto &SubFEOpts = subInvocation.getFrontendOptions();
    SubFEOpts.RequestedAction = FrontendOptions::ActionType::EmitModuleOnly;
    SubFEOpts.InputsAndOutputs.addPrimaryInputFile(interfacePath);
    SupplementaryOutputPaths SOPs;
    SOPs.ModuleOutputPath = OutPath.str();

    // Pick a primary output path that will cause problems to use.
    StringRef MainOut = "/<unused>";
    SubFEOpts.InputsAndOutputs
      .setMainAndSupplementaryOutputs({MainOut}, {SOPs});
  }

  void configureSubInvocation() {
    auto &SearchPathOpts = ctx.SearchPathOpts;
    auto &LangOpts = ctx.LangOpts;

    // Start with a SubInvocation that copies various state from our
    // invoking ASTContext.
    subInvocation.setImportSearchPaths(SearchPathOpts.ImportSearchPaths);
    subInvocation.setFrameworkSearchPaths(SearchPathOpts.FrameworkSearchPaths);
    subInvocation.setSDKPath(SearchPathOpts.SDKPath);
    subInvocation.setInputKind(InputFileKind::SwiftModuleInterface);
    subInvocation.setRuntimeResourcePath(SearchPathOpts.RuntimeResourcePath);
    subInvocation.setTargetTriple(LangOpts.Target);

    subInvocation.setModuleName(moduleName);
    subInvocation.setClangModuleCachePath(moduleCachePath);
    subInvocation.getFrontendOptions().PrebuiltModuleCachePath =
      prebuiltCachePath;
    subInvocation.getFrontendOptions().TrackSystemDeps = trackSystemDependencies;

    // Respect the detailed-record preprocessor setting of the parent context.
    // This, and the "raw" clang module format it implicitly enables, are
    // required by sourcekitd.
    if (auto *ClangLoader = ctx.getClangModuleLoader()) {
      auto &Opts = ClangLoader->getClangInstance().getPreprocessorOpts();
      if (Opts.DetailedRecord) {
        subInvocation.getClangImporterOptions().DetailedPreprocessingRecord = true;
      }
    }

    // Inhibit warnings from the SubInvocation since we are assuming the user
    // is not in a position to fix them.
    subInvocation.getDiagnosticOptions().SuppressWarnings = true;

    // Inherit this setting down so that it can affect error diagnostics (mostly
    // by making them non-fatal).
    subInvocation.getLangOptions().DebuggerSupport = LangOpts.DebuggerSupport;

    // Disable this; deinitializers always get printed with `@objc` even in
    // modules that don't import Foundation.
    subInvocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;

    // Tell the subinvocation to serialize dependency hashes if asked to do so.
    auto &frontendOpts = subInvocation.getFrontendOptions();
    frontendOpts.SerializeParseableModuleInterfaceDependencyHashes =
      serializeDependencyHashes;
  }

  bool extractSwiftInterfaceVersionAndArgs(
    swift::version::Version &Vers, llvm::StringSaver &SubArgSaver,
    SmallVectorImpl<const char *> &SubArgs) {
    auto FileOrError = swift::vfs::getFileOrSTDIN(fs, interfacePath);
    if (!FileOrError) {
      diags.diagnose(diagnosticLoc, diag::error_open_input_file,
                     interfacePath, FileOrError.getError().message());
      return true;
    }
    auto SB = FileOrError.get()->getBuffer();
    auto VersRe = getSwiftInterfaceFormatVersionRegex();
    auto FlagRe = getSwiftInterfaceModuleFlagsRegex();
    SmallVector<StringRef, 1> VersMatches, FlagMatches;
    if (!VersRe.match(SB, &VersMatches)) {
      diags.diagnose(diagnosticLoc,
                     diag::error_extracting_version_from_parseable_interface);
      return true;
    }
    if (!FlagRe.match(SB, &FlagMatches)) {
      diags.diagnose(diagnosticLoc,
                     diag::error_extracting_flags_from_parseable_interface);
      return true;
    }
    assert(VersMatches.size() == 2);
    assert(FlagMatches.size() == 2);
    Vers = swift::version::Version(VersMatches[1], SourceLoc(), &diags);
    llvm::cl::TokenizeGNUCommandLine(FlagMatches[1], SubArgSaver, SubArgs);
    return false;
  }

  /// Populate the provided \p Deps with \c FileDependency entries for all
  /// dependencies \p SubInstance's DependencyTracker recorded while compiling
  /// the module, excepting .swiftmodules in \p moduleCachePath or
  /// \p prebuiltCachePath. Those have _their_ dependencies added instead, both
  /// to avoid having to do recursive scanning when rechecking this dependency
  /// in future and to make the module caches relocatable.
  bool collectDepsForSerialization(CompilerInstance &SubInstance,
                                   SmallVectorImpl<FileDependency> &Deps,
                                   bool IsHashBased) {
    StringRef SDKPath = SubInstance.getASTContext().SearchPathOpts.SDKPath;
    StringRef ResourcePath =
        SubInstance.getASTContext().SearchPathOpts.RuntimeResourcePath;
    auto DTDeps = SubInstance.getDependencyTracker()->getDependencies();
    SmallVector<StringRef, 16> InitialDepNames(DTDeps.begin(), DTDeps.end());
    InitialDepNames.push_back(interfacePath);
    llvm::StringSet<> AllDepNames;

    for (auto const &DepName : InitialDepNames) {
      assert(moduleCachePath.empty() || !DepName.startswith(moduleCachePath));
      assert(prebuiltCachePath.empty() || !DepName.startswith(prebuiltCachePath));

      /// Lazily load the dependency buffer if we need it. If we're not
      /// dealing with a hash-based dependencies, and if the dependency is
      /// not a .swiftmodule, we can avoid opening the buffer.
      std::unique_ptr<llvm::MemoryBuffer> DepBuf = nullptr;
      auto getDepBuf = [&]() -> llvm::MemoryBuffer * {
        if (DepBuf) return DepBuf.get();
        if (auto Buf = getBufferOfDependency(fs, DepName, interfacePath,
                                             diags, diagnosticLoc)) {
          DepBuf = std::move(Buf);
          return DepBuf.get();
        }
        return nullptr;
      };

      // Adjust the paths of dependences in the SDK to be relative to it
      bool IsSDKRelative = false;
      StringRef DepNameToStore = DepName;
      if (SDKPath.size() > 1 && DepName.startswith(SDKPath)) {
        assert(DepName.size() > SDKPath.size() &&
            "should never depend on a directory");
        if (llvm::sys::path::is_separator(DepName[SDKPath.size()])) {
          // Is the DepName something like ${SDKPath}/foo.h"?
          DepNameToStore = DepName.substr(SDKPath.size() + 1);
          IsSDKRelative = true;
        } else if (llvm::sys::path::is_separator(SDKPath.back())) {
          // Is the DepName something like "${SDKPath}foo.h", where SDKPath
          // itself contains a trailing slash?
          DepNameToStore = DepName.substr(SDKPath.size());
          IsSDKRelative = true;
        } else {
          // We have something next to an SDK, like "Foo.sdk.h", that's somehow
          // become a dependency.
        }
      }

      if (AllDepNames.insert(DepName).second && dependencyTracker) {
        dependencyTracker->addDependency(DepName, /*isSystem*/IsSDKRelative);
      }

      // Don't serialize compiler-relative deps so the cache is relocatable.
      if (DepName.startswith(ResourcePath))
        continue;

      auto Status = getStatusOfDependency(fs, DepName, interfacePath,
                                          diags, diagnosticLoc);
      if (!Status)
        return true;

      if (IsHashBased) {
        auto buf = getDepBuf();
        if (!buf) return true;
        uint64_t hash = xxHash64(buf->getBuffer());
        Deps.push_back(
          FileDependency::hashBased(DepNameToStore, IsSDKRelative,
                                    Status->getSize(), hash));
      } else {
        uint64_t mtime =
          Status->getLastModificationTime().time_since_epoch().count();
        Deps.push_back(
          FileDependency::modTimeBased(DepNameToStore, IsSDKRelative,
                                       Status->getSize(), mtime));
      }
    }
    return false;
  }

public:
  ParseableInterfaceBuilder(ASTContext &ctx,
                            StringRef interfacePath,
                            StringRef moduleName,
                            StringRef moduleCachePath,
                            StringRef prebuiltCachePath,
                            bool serializeDependencyHashes = false,
                            bool trackSystemDependencies = false,
                            SourceLoc diagnosticLoc = SourceLoc(),
                            DependencyTracker *tracker = nullptr)
  : ctx(ctx), fs(*ctx.SourceMgr.getFileSystem()), diags(ctx.Diags),
  interfacePath(interfacePath), moduleName(moduleName),
  moduleCachePath(moduleCachePath), prebuiltCachePath(prebuiltCachePath),
  serializeDependencyHashes(serializeDependencyHashes),
  trackSystemDependencies(trackSystemDependencies),
  diagnosticLoc(diagnosticLoc), dependencyTracker(tracker) {
    configureSubInvocation();
  }

  const CompilerInvocation &getSubInvocation() const {
    return subInvocation;
  }

  bool buildSwiftModule(StringRef OutPath, bool ShouldSerializeDeps,
                        std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer) {
    bool SubError = false;
    bool RunSuccess = llvm::CrashRecoveryContext().RunSafelyOnThread([&] {
      // Note that we don't assume cachePath is the same as the Clang
      // module cache path at this point.
      if (!moduleCachePath.empty())
        (void)llvm::sys::fs::create_directory(moduleCachePath);

      configureSubInvocationInputsAndOutputs(OutPath);

      FrontendOptions &FEOpts = subInvocation.getFrontendOptions();
      const auto &InputInfo = FEOpts.InputsAndOutputs.firstInput();
      StringRef InPath = InputInfo.file();
      const auto &OutputInfo =
        InputInfo.getPrimarySpecificPaths().SupplementaryOutputs;
      StringRef OutPath = OutputInfo.ModuleOutputPath;

      llvm::BumpPtrAllocator SubArgsAlloc;
      llvm::StringSaver SubArgSaver(SubArgsAlloc);
      SmallVector<const char *, 16> SubArgs;
      swift::version::Version Vers;
      if (extractSwiftInterfaceVersionAndArgs(Vers, SubArgSaver, SubArgs)) {
        SubError = true;
        return;
      }

      // For now: we support anything with the same "major version" and assume
      // minor versions might be interesting for debugging, or special-casing a
      // compatible field variant.
      if (Vers.asMajorVersion() != InterfaceFormatVersion.asMajorVersion()) {
        diags.diagnose(diagnosticLoc,
                       diag::unsupported_version_of_parseable_interface,
                       interfacePath, Vers);
        SubError = true;
        return;
      }

      SmallString<32> ExpectedModuleName = subInvocation.getModuleName();
      if (subInvocation.parseArgs(SubArgs, diags)) {
        SubError = true;
        return;
      }

      if (subInvocation.getModuleName() != ExpectedModuleName) {
        auto DiagKind = diag::serialization_name_mismatch;
        if (subInvocation.getLangOptions().DebuggerSupport)
          DiagKind = diag::serialization_name_mismatch_repl;
        diags.diagnose(diagnosticLoc, DiagKind, subInvocation.getModuleName(),
                       ExpectedModuleName);
        SubError = true;
        return;
      }

      // Optimize emitted modules. This has to happen after we parse arguments,
      // because parseSILOpts would override the current optimization mode.
      subInvocation.getSILOptions().OptMode = OptimizationMode::ForSpeed;

      // Build the .swiftmodule; this is a _very_ abridged version of the logic
      // in performCompile in libFrontendTool, specialized, to just the one
      // module-serialization task we're trying to do here.
      LLVM_DEBUG(llvm::dbgs() << "Setting up instance to compile "
                 << InPath << " to " << OutPath << "\n");
      CompilerInstance SubInstance;
      SubInstance.getSourceMgr().setFileSystem(&fs);

      ForwardingDiagnosticConsumer FDC(diags);
      SubInstance.addDiagnosticConsumer(&FDC);

      SubInstance.createDependencyTracker(FEOpts.TrackSystemDeps);

      if (SubInstance.setup(subInvocation)) {
        SubError = true;
        return;
      }

      LLVM_DEBUG(llvm::dbgs() << "Performing sema\n");
      SubInstance.performSema();
      if (SubInstance.getASTContext().hadError()) {
        LLVM_DEBUG(llvm::dbgs() << "encountered errors\n");
        SubError = true;
        return;
      }

      SILOptions &SILOpts = subInvocation.getSILOptions();
      auto Mod = SubInstance.getMainModule();
      auto SILMod = performSILGeneration(Mod, SILOpts);
      if (!SILMod) {
        LLVM_DEBUG(llvm::dbgs() << "SILGen did not produce a module\n");
        SubError = true;
        return;
      }

      // Setup the callbacks for serialization, which can occur during the
      // optimization pipeline.
      SerializationOptions SerializationOpts;
      std::string OutPathStr = OutPath;
      SerializationOpts.OutputPath = OutPathStr.c_str();
      SerializationOpts.ModuleLinkName = FEOpts.ModuleLinkName;
      SmallVector<FileDependency, 16> Deps;
      if (collectDepsForSerialization(SubInstance, Deps,
            FEOpts.SerializeParseableModuleInterfaceDependencyHashes)) {
        SubError = true;
        return;
      }
      if (ShouldSerializeDeps)
        SerializationOpts.Dependencies = Deps;
      SILMod->setSerializeSILAction([&]() {
        // We don't want to serialize module docs in the cache -- they
        // will be serialized beside the interface file.
        serializeToBuffers(Mod, SerializationOpts, ModuleBuffer,
                           /*ModuleDocBuffer*/nullptr, SILMod.get());
      });

      LLVM_DEBUG(llvm::dbgs() << "Running SIL processing passes\n");
      if (SubInstance.performSILProcessing(SILMod.get())) {
        LLVM_DEBUG(llvm::dbgs() << "encountered errors\n");
        SubError = true;
        return;
      }

      SubError = SubInstance.getDiags().hadAnyError();
    });
    return !RunSuccess || SubError;
  }
};

#pragma mark - Module Loading

namespace {

/// Handles the details of loading parseable interfaces as modules, and will
/// do the necessary lookup to determine if we should be loading from the
/// normal cache, the prebuilt cache, a module adjacent to the interface, or
/// a module that we'll build from a parseable interface.
class ParseableInterfaceModuleLoaderImpl {
  using AccessPathElem = std::pair<Identifier, SourceLoc>;
  friend class swift::ParseableInterfaceModuleLoader;
  ASTContext &ctx;
  llvm::vfs::FileSystem &fs;
  DiagnosticEngine &diags;
  const StringRef modulePath;
  const std::string interfacePath;
  const StringRef moduleName;
  const StringRef prebuiltCacheDir;
  const StringRef cacheDir;
  const SourceLoc diagnosticLoc;
  DependencyTracker *const dependencyTracker;
  const ModuleLoadingMode loadMode;

  ParseableInterfaceModuleLoaderImpl(
    ASTContext &ctx, StringRef modulePath, StringRef interfacePath,
    StringRef moduleName, StringRef cacheDir, StringRef prebuiltCacheDir,
    SourceLoc diagLoc, DependencyTracker *dependencyTracker = nullptr,
    ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized)
  : ctx(ctx), fs(*ctx.SourceMgr.getFileSystem()), diags(ctx.Diags),
    modulePath(modulePath), interfacePath(interfacePath),
    moduleName(moduleName), prebuiltCacheDir(prebuiltCacheDir),
    cacheDir(cacheDir), diagnosticLoc(diagLoc),
    dependencyTracker(dependencyTracker), loadMode(loadMode) {}

  /// Construct a cache key for the .swiftmodule being generated. There is a
  /// balance to be struck here between things that go in the cache key and
  /// things that go in the "up to date" check of the cache entry. We want to
  /// avoid fighting over a single cache entry too much when (say) running
  /// different compiler versions on the same machine or different inputs
  /// that happen to have the same short module name, so we will disambiguate
  /// those in the key. But we want to invalidate and rebuild a cache entry
  /// -- rather than making a new one and potentially filling up the cache
  /// with dead entries -- when other factors change, such as the contents of
  /// the .swiftinterface input or its dependencies.
  std::string getCacheHash(const CompilerInvocation &SubInvocation) {
    // Start with the compiler version (which will be either tag names or revs).
    // Explicitly don't pass in the "effective" language version -- this would
    // mean modules built in different -swift-version modes would rebuild their
    // dependencies.
    llvm::hash_code H = hash_value(swift::version::getSwiftFullVersion());

    // Simplest representation of input "identity" (not content) is just a
    // pathname, and probably all we can get from the VFS in this regard
    // anyways.
    H = hash_combine(H, interfacePath);

    // Include the target CPU architecture. In practice, .swiftinterface files
    // will be in architecture-specific subdirectories and would have
    // architecture-specific pieces #if'd out. However, it doesn't hurt to
    // include it, and it guards against mistakenly reusing cached modules
    // across architectures.
    H = hash_combine(H, SubInvocation.getLangOptions().Target.getArchName());

    // The SDK path is going to affect how this module is imported, so include
    // it.
    H = hash_combine(H, SubInvocation.getSDKPath());

    // Whether or not we're tracking system dependencies affects the
    // invalidation behavior of this cache item.
    H = hash_combine(H, SubInvocation.getFrontendOptions().TrackSystemDeps);

    return llvm::APInt(64, H).toString(36, /*Signed=*/false);
  }

  /// Calculate an output filename in \p SubInvocation's cache path that
  /// includes a hash of relevant key data.
  void computeCachedOutputPath(const CompilerInvocation &SubInvocation,
                               llvm::SmallString<256> &OutPath) {
    OutPath = SubInvocation.getClangModuleCachePath();
    llvm::sys::path::append(OutPath, SubInvocation.getModuleName());
    OutPath.append("-");
    OutPath.append(getCacheHash(SubInvocation));
    OutPath.append(".");
    auto OutExt = file_types::getExtension(file_types::TY_SwiftModuleFile);
    OutPath.append(OutExt);
  }

  /// Constructs the full path of the dependency \p dep by prepending the SDK
  /// path if necessary.
  StringRef getFullDependencyPath(const FileDependency &dep,
                                  SmallVectorImpl<char> &scratch) const {
    if (!dep.isSDKRelative())
      return dep.getPath();

    StringRef SDKPath = ctx.SearchPathOpts.SDKPath;
    scratch.assign(SDKPath.begin(), SDKPath.end());
    llvm::sys::path::append(scratch, dep.getPath());
    return StringRef(scratch.data(), scratch.size());
  }

  // Checks that a dependency read from the cached module is up to date compared
  // to the interface file it represents.
  bool dependencyIsUpToDate(const FileDependency &dep, StringRef fullPath) {
    auto status = getStatusOfDependency(fs, fullPath, interfacePath,
                                        diags, diagnosticLoc);
    if (!status) return false;

    // If the sizes differ, then we know the file has changed.
    if (status->getSize() != dep.getSize()) return false;

    // Otherwise, if this dependency is verified by modification time, check
    // it vs. the modification time of the file.
    if (dep.isModificationTimeBased()) {
      uint64_t mtime =
        status->getLastModificationTime().time_since_epoch().count();
      return mtime == dep.getModificationTime();
    }

    // Slow path: if the dependency is verified by content hash, check it vs.
    // the hash of the file.
    auto buf = getBufferOfDependency(fs, fullPath, interfacePath,
                                     diags, diagnosticLoc);
    if (!buf) return false;

    return xxHash64(buf->getBuffer()) == dep.getContentHash();
  }

  // Check if all the provided file dependencies are up-to-date compared to
  // what's currently on disk.
  bool dependenciesAreUpToDate(ArrayRef<FileDependency> deps) {
    SmallString<128> SDKRelativeBuffer;
    for (auto &in : deps) {
      StringRef fullPath = getFullDependencyPath(in, SDKRelativeBuffer);
      if (!dependencyIsUpToDate(in, fullPath)) {
        LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath
                   << " is directly out of date\n");
        return false;
      }
      LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is up to date\n");
    }
    return true;
  }

  // Check that the output .swiftmodule file is at least as new as all the
  // dependencies it read when it was built last time.
  bool serializedASTBufferIsUpToDate(
    const llvm::MemoryBuffer &buf, SmallVectorImpl<FileDependency> &allDeps) {
    LLVM_DEBUG(llvm::dbgs() << "Validating deps of " << modulePath << "\n");
    auto validationInfo = serialization::validateSerializedAST(
        buf.getBuffer(), /*ExtendedValidationInfo=*/nullptr, &allDeps);

    if (validationInfo.status != serialization::Status::Valid)
      return false;

    return dependenciesAreUpToDate(allDeps);
  }

  // Check that the output .swiftmodule file is at least as new as all the
  // dependencies it read when it was built last time.
  bool swiftModuleIsUpToDate(
    StringRef modulePath, SmallVectorImpl<FileDependency> &AllDeps,
    std::unique_ptr<llvm::MemoryBuffer> &moduleBuffer) {
    auto OutBuf = fs.getBufferForFile(modulePath);
    if (!OutBuf)
      return false;
    moduleBuffer = std::move(*OutBuf);
    return serializedASTBufferIsUpToDate(*moduleBuffer, AllDeps);
  }

  // Check that a "forwarding" .swiftmodule file is at least as new as all the
  // dependencies it read when it was built last time. Requires that the
  // forwarding module has been loaded from disk.
  bool forwardingModuleIsUpToDate(
    const ForwardingModule &fwd, SmallVectorImpl<FileDependency> &deps,
    std::unique_ptr<llvm::MemoryBuffer> &moduleBuffer) {
    // First, make sure the underlying module path exists and is valid.
    auto modBuf = fs.getBufferForFile(fwd.underlyingModulePath);
    if (!modBuf || !serializedASTLooksValid(*modBuf.get()))
      return false;

    // Next, check the dependencies in the forwarding file.
    for (auto &dep : fwd.dependencies) {
      // Forwarding modules expand SDKRelative paths when generated, so are
      // guaranteed to be absolute.
      deps.push_back(
        FileDependency::modTimeBased(
          dep.path, /*isSDKRelative=*/false, dep.size,
          dep.lastModificationTime));
    }
    if (!dependenciesAreUpToDate(deps))
      return false;

    moduleBuffer = std::move(*modBuf);
    return true;
  }

  Optional<StringRef>
  computePrebuiltModulePath(llvm::SmallString<256> &scratch) {
    namespace path = llvm::sys::path;
    StringRef sdkPath = ctx.SearchPathOpts.SDKPath;

    // Check if the interface file comes from the SDK
    if (sdkPath.empty() || !hasPrefix(path::begin(interfacePath),
                                      path::end(interfacePath),
                                      path::begin(sdkPath),
                                      path::end(sdkPath)))
      return None;

    // Assemble the expected path: $PREBUILT_CACHE/Foo.swiftmodule or
    // $PREBUILT_CACHE/Foo.swiftmodule/arch.swiftmodule. Note that there's no
    // cache key here.
    scratch.append(prebuiltCacheDir);

    // FIXME: Would it be possible to only have architecture-specific names
    // here? Then we could skip this check.
    StringRef inParentDirName =
      path::filename(path::parent_path(interfacePath));
    if (path::extension(inParentDirName) == ".swiftmodule") {
      assert(path::stem(inParentDirName) == moduleName);
      path::append(scratch, inParentDirName);
    }
    path::append(scratch, path::filename(modulePath));

    return scratch.str();
  }

  /// Finds the most appropriate .swiftmodule, whose dependencies are up to
  /// date, that we can load for the provided .swiftinterface file.
  llvm::ErrorOr<DiscoveredModule> discoverUpToDateModuleForInterface(
    StringRef modulePath, StringRef cachedOutputPath,
    SmallVectorImpl<FileDependency> &deps) {
    auto notFoundError =
      std::make_error_code(std::errc::no_such_file_or_directory);

    // Keep track of whether we should attempt to load a .swiftmodule adjacent
    // to the .swiftinterface.
    bool shouldLoadAdjacentModule = true;

    switch (loadMode) {
    case ModuleLoadingMode::OnlyParseable:
      // Always skip both the caches and adjacent modules, and always build the
      // parseable interface.
      return notFoundError;
    case ModuleLoadingMode::PreferParseable:
      // If we're in the load mode that prefers .swiftinterfaces, specifically
      // skip the module adjacent to the interface, but use the caches if
      // they're present.
      shouldLoadAdjacentModule = false;
      break;
    case ModuleLoadingMode::PreferSerialized:
      // The rest of the function should be covered by this.
      break;
    case ModuleLoadingMode::OnlySerialized:
      llvm_unreachable("parseable module loader should not have been created");
    }

    // First, check the cached module path. Whatever's in this cache represents
    // the most up-to-date knowledge we have about the module.
    if (auto cachedBufOrError = fs.getBufferForFile(cachedOutputPath)) {
      auto buf = std::move(*cachedBufOrError);

      // Check to see if the module is a serialized AST. If it's not, then we're
      // probably dealing with a Forwarding Module, which is a YAML file.
      bool isForwardingModule =
        !serialization::isSerializedAST(buf->getBuffer());

      // If it's a forwarding module, load the YAML file from disk and check
      // if it's up-to-date.
      if (isForwardingModule) {
        if (auto forwardingModule = ForwardingModule::load(*buf)) {
          std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
          if (forwardingModuleIsUpToDate(*forwardingModule, deps, moduleBuffer))
            return DiscoveredModule::forwarded(
              forwardingModule->underlyingModulePath, std::move(moduleBuffer));
        }
      // Otherwise, check if the AST buffer itself is up to date.
      } else if (serializedASTBufferIsUpToDate(*buf, deps)) {
        return DiscoveredModule::normal(cachedOutputPath, std::move(buf));
      }
    }

    // If we weren't able to open the file for any reason, including it not
    // existing, keep going.

    // If we have a prebuilt cache path, check that too if the interface comes
    // from the SDK.
    if (!prebuiltCacheDir.empty()) {
      llvm::SmallString<256> scratch;
      std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
      auto path = computePrebuiltModulePath(scratch);
      if (path && swiftModuleIsUpToDate(*path, deps, moduleBuffer))
        return DiscoveredModule::prebuilt(*path, std::move(moduleBuffer));
    }

    // Finally, if there's a module adjacent to the .swiftinterface that we can
    // _likely_ load (it validates OK and is up to date), bail early with
    // errc::not_supported, so the next (serialized) loader in the chain will
    // load it. Alternately, if there's a .swiftmodule present but we can't even
    // read it (for whatever reason), we should let the other module loader
    // diagnose it.
    if (!shouldLoadAdjacentModule)
      return notFoundError;

    auto adjacentModuleBuffer = fs.getBufferForFile(modulePath);
    if (adjacentModuleBuffer) {
      if (serializedASTBufferIsUpToDate(*adjacentModuleBuffer.get(), deps))
        return std::make_error_code(std::errc::not_supported);
    } else if (adjacentModuleBuffer.getError() != notFoundError) {
      return std::make_error_code(std::errc::not_supported);
    }

    // Couldn't find an up-to-date .swiftmodule, will need to build module from
    // interface.
    return notFoundError;
  }

  /// Writes the "forwarding module" that will forward to a module in the
  /// prebuilt cache.
  /// Since forwarding modules track dependencies separately from the module
  /// they point to, we'll need to grab the up-to-date file status while doing
  /// this.
  bool writeForwardingModule(const DiscoveredModule &mod,
                             StringRef outputPath,
                             ArrayRef<FileDependency> deps) {
    assert(mod.isPrebuilt() &&
           "cannot write forwarding file for non-prebuilt module");
    ForwardingModule fwd(mod.path);

    // FIXME: We need to avoid re-statting all these dependencies, otherwise
    //        we may record out-of-date information.
    auto addDependency = [&](StringRef path) {
      auto status = fs.status(path);
      uint64_t mtime =
        status->getLastModificationTime().time_since_epoch().count();
      fwd.addDependency(path, status->getSize(), mtime);
    };

    // Add the prebuilt module as a dependency of the forwarding module.
    addDependency(fwd.underlyingModulePath);

    // Add all the dependencies from the prebuilt module.
    SmallString<128> SDKRelativeBuffer;
    for (auto dep : deps) {
      addDependency(getFullDependencyPath(dep, SDKRelativeBuffer));
    }

    return withOutputFile(diags, outputPath,
      [&](llvm::raw_pwrite_stream &out) {
        llvm::yaml::Output yamlWriter(out);
        yamlWriter << fwd;
        return false;
      });
  }

  /// Looks up the best module to load for a given interface, and returns a
  /// buffer of the module's contents. Also reports the module's dependencies
  /// to the parent \c dependencyTracker if it came from the cache, or was built
  /// from the given interface. See the main comment in
  /// \c ParseableInterfaceModuleLoader.h for an explanation of the module
  /// loading strategy.
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
  findOrBuildLoadableModule() {

    // Track system dependencies if the parent tracker is set to do so.
    // FIXME: This means -track-system-dependencies isn't honored when the
    // top-level invocation isn't tracking dependencies
    bool trackSystemDependencies = false;
    if (dependencyTracker) {
      auto ClangDependencyTracker = dependencyTracker->getClangCollector();
      trackSystemDependencies = ClangDependencyTracker->needSystemDependencies();
    }

    // Set up a builder if we need to build the module. It'll also set up
    // the subinvocation we'll need to use to compute the cache paths.
    ParseableInterfaceBuilder builder(
      ctx, interfacePath, moduleName, cacheDir, prebuiltCacheDir,
      /*serializeDependencyHashes*/false, trackSystemDependencies,
      diagnosticLoc, dependencyTracker);
    auto &subInvocation = builder.getSubInvocation();

    // Compute the output path if we're loading or emitting a cached module.
    llvm::SmallString<256> cachedOutputPath;
    computeCachedOutputPath(subInvocation, cachedOutputPath);

    // Try to find the right module for this interface, either alongside it,
    // in the cache, or in the prebuilt cache.
    SmallVector<FileDependency, 16> allDeps;
    auto moduleOrErr =
      discoverUpToDateModuleForInterface(modulePath, cachedOutputPath, allDeps);

    // If we errored with anything other than 'no such file or directory',
    // fail this load and let the other module loader diagnose it.
    if (!moduleOrErr &&
        moduleOrErr.getError() != std::errc::no_such_file_or_directory)
      return moduleOrErr.getError();

    // We discovered a module! Return that module's buffer so we can load it.
    if (moduleOrErr) {
      auto module = std::move(moduleOrErr.get());

      // If it's prebuilt, use this time to generate a forwarding module.
      if (module.isPrebuilt())
        if (writeForwardingModule(module, cachedOutputPath, allDeps))
          return std::make_error_code(std::errc::not_supported);

      // Report the module's dependencies to the dependencyTracker
      if (dependencyTracker) {
        SmallString<128> SDKRelativeBuffer;
        for (auto &dep: allDeps) {
          StringRef fullPath = getFullDependencyPath(dep, SDKRelativeBuffer);
          dependencyTracker->addDependency(fullPath, dep.isSDKRelative());
        }
      }

      return std::move(module.moduleBuffer);
    }

    std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
    // We didn't discover a module corresponding to this interface. Build one.
    if (builder.buildSwiftModule(cachedOutputPath, /*shouldSerializeDeps*/true,
                                 &moduleBuffer))
      return std::make_error_code(std::errc::invalid_argument);

    assert(moduleBuffer &&
           "failed to write module buffer but returned success?");
    return std::move(moduleBuffer);
  }
};

} // end anonymous namespace

bool ParseableInterfaceModuleLoader::isCached(StringRef DepPath) {
  if (!CacheDir.empty() && DepPath.startswith(CacheDir))
    return true;
  return !PrebuiltCacheDir.empty() && DepPath.startswith(PrebuiltCacheDir);
}

/// Load a .swiftmodule associated with a .swiftinterface either from a
/// cache or by converting it in a subordinate \c CompilerInstance, caching
/// the results.
std::error_code ParseableInterfaceModuleLoader::findModuleFilesInDirectory(
  AccessPathElem ModuleID, StringRef DirPath, StringRef ModuleFilename,
  StringRef ModuleDocFilename,
  std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
  std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) {

  // If running in OnlySerialized mode, ParseableInterfaceModuleLoader
  // should not have been constructed at all.
  assert(LoadMode != ModuleLoadingMode::OnlySerialized);

  auto &fs = *Ctx.SourceMgr.getFileSystem();
  llvm::SmallString<256> ModPath, InPath;

  // First check to see if the .swiftinterface exists at all. Bail if not.
  ModPath = DirPath;
  path::append(ModPath, ModuleFilename);

  auto Ext = file_types::getExtension(file_types::TY_SwiftParseableInterfaceFile);
  InPath = ModPath;
  path::replace_extension(InPath, Ext);
  if (!fs.exists(InPath))
    return std::make_error_code(std::errc::no_such_file_or_directory);

  // Create an instance of the Impl to do the heavy lifting.
  ParseableInterfaceModuleLoaderImpl Impl(
                Ctx, ModPath, InPath, ModuleID.first.str(),
                CacheDir, PrebuiltCacheDir, ModuleID.second, dependencyTracker,
                LoadMode);

  // Ask the impl to find us a module that we can load or give us an error
  // telling us that we couldn't load it.
  auto ModuleBufferOrErr = Impl.findOrBuildLoadableModule();
  if (!ModuleBufferOrErr)
    return ModuleBufferOrErr.getError();

  if (ModuleBuffer) {
    *ModuleBuffer = std::move(*ModuleBufferOrErr);
  }

  // Delegate back to the serialized module loader to load the module doc.
  llvm::SmallString<256> DocPath{DirPath};
  path::append(DocPath, ModuleDocFilename);
  auto DocLoadErr =
    SerializedModuleLoaderBase::openModuleDocFile(ModuleID, DocPath,
                                                  ModuleDocBuffer);
  if (DocLoadErr)
    return DocLoadErr;

  return std::error_code();
}


bool ParseableInterfaceModuleLoader::buildSwiftModuleFromSwiftInterface(
  ASTContext &Ctx, StringRef CacheDir, StringRef PrebuiltCacheDir,
  StringRef ModuleName, StringRef InPath, StringRef OutPath,
  bool SerializeDependencyHashes, bool TrackSystemDependencies) {
  ParseableInterfaceBuilder builder(Ctx, InPath, ModuleName,
                                    CacheDir, PrebuiltCacheDir,
                                    SerializeDependencyHashes,
                                    TrackSystemDependencies);
  // FIXME: We really only want to serialize 'important' dependencies here, if
  //        we want to ship the built swiftmodules to another machine.
  return builder.buildSwiftModule(OutPath, /*shouldSerializeDeps*/true,
                                  /*ModuleBuffer*/nullptr);
}
