//===- ModuleManager.cpp - Module Manager ---------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file defines the ModuleManager class, which manages a set of loaded
//  modules for the ASTReader.
//
//===----------------------------------------------------------------------===//

#include "clang/Serialization/ModuleManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "clang/Serialization/InMemoryModuleCache.h"
#include "clang/Serialization/ModuleCache.h"
#include "clang/Serialization/ModuleFile.h"
#include "clang/Serialization/PCHContainerOperations.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Support/DOTGraphTraits.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <cassert>
#include <memory>
#include <string>
#include <system_error>

using namespace clang;
using namespace serialization;

std::optional<ModuleFileKey>
ModuleManager::makeKey(const ModuleFileName &Name) const {
  if (unsigned SuffixLen = Name.getImplicitModuleSuffixLength()) {
    StringRef ModuleCachePath = StringRef(Name).drop_back(SuffixLen);
    StringRef ImplicitModuleSuffix = StringRef(Name).take_back(SuffixLen);
    if (auto *ModuleCacheDir = ModCache.getDirectoryPtr(ModuleCachePath))
      return ModuleFileKey(ModuleCacheDir, ImplicitModuleSuffix);
  } else if (Name.isInMemory()) {
    off_t Size;
    time_t ModTime;
    if (auto *Buf =
            ModCache.getInMemoryModuleCache().lookupPCM(Name, Size, ModTime))
      return ModuleFileKey(Buf);
  } else {
    if (auto ModuleFile = FileMgr.getOptionalFileRef(Name, /*OpenFile=*/true,
                                                     /*CacheFailure=*/true,
                                                     /*IsText=*/false))
      return ModuleFileKey(*ModuleFile);
  }

  return std::nullopt;
}

ModuleFile *ModuleManager::lookupByModuleName(StringRef Name) const {
  if (const Module *Mod = HeaderSearchInfo.getModuleMap().findModule(Name))
    if (const ModuleFileName *FileName = Mod->getASTFileName())
      return lookupByFileName(*FileName);

  return nullptr;
}

ModuleFile *ModuleManager::lookupByFileName(ModuleFileName Name) const {
  std::optional<ModuleFileKey> Key = makeKey(Name);
  return Key ? lookup(*Key) : nullptr;
}

ModuleFile *ModuleManager::lookup(ModuleFileKey Key) const {
  return Modules.lookup(Key);
}

bool ModuleManager::isModuleFileOutOfDate(off_t Size, time_t ModTime,
                                          off_t ExpectedSize,
                                          time_t ExpectedModTime,
                                          AddModuleResult &Result) {
  bool OutOfDate = false;
  if (ExpectedSize && ExpectedSize != Size) {
    Result.Changes.push_back({Change::Size, ExpectedSize, Size});
    OutOfDate = true;
  }

  if (ExpectedModTime && ExpectedModTime != ModTime) {
    Result.Changes.push_back({Change::ModTime, ExpectedModTime, ModTime});
    OutOfDate = true;
  }

  return OutOfDate;
}

bool ModuleManager::checkSignature(ASTFileSignature Signature,
                                   ASTFileSignature ExpectedSignature,
                                   AddModuleResult &Result) {
  if (!ExpectedSignature || Signature == ExpectedSignature)
    return false;
  Result.SignatureError =
      Signature ? "signature mismatch" : "could not read module signature";
  return true;
}

static void updateModuleImports(ModuleFile &MF, ModuleFile *ImportedBy,
                                SourceLocation ImportLoc) {
  if (ImportedBy) {
    MF.ImportedBy.insert(ImportedBy);
    ImportedBy->Imports.insert(&MF);
  } else {
    if (!MF.DirectlyImported)
      MF.ImportLoc = ImportLoc;

    MF.DirectlyImported = true;
  }
}

AddModuleResult ModuleManager::addModule(
    ModuleFileName FileName, ModuleKind Type, SourceLocation ImportLoc,
    ModuleFile *ImportedBy, unsigned Generation, off_t ExpectedSize,
    time_t ExpectedModTime, ASTFileSignature ExpectedSignature,
    ASTFileSignatureReader ReadSignature) {
  AddModuleResult Result;

  uint64_t InputFilesValidationTimestamp = 0;
  if (Type == MK_ImplicitModule)
    InputFilesValidationTimestamp = ModCache.getModuleTimestamp(FileName);

  bool IgnoreModTime = Type == MK_ExplicitModule || Type == MK_PrebuiltModule;
  if (ImportedBy)
    IgnoreModTime &= ImportedBy->Kind == MK_ExplicitModule ||
                     ImportedBy->Kind == MK_PrebuiltModule;
  if (IgnoreModTime) {
    // If neither this file nor the importer are in the module cache, this file
    // might have a different mtime due to being moved across filesystems in
    // a distributed build. The size must still match, though. (As must the
    // contents, but we can't check that.)
    ExpectedModTime = 0;
  }

  std::optional<ModuleFileKey> FileKey = makeKey(FileName);
  if (!FileKey) {
    Result.K = AddModuleResult::Missing;
    return Result;
  }

  // Check whether we already loaded this module before.
  // Note: `isModuleFileOutOfDate` and `checkSignature` are mutually exclusive
  // in practice. If a signature is stored, it means size/mtime values have been
  // zeroed out. If size/mtime are non-NULL, the signature is empty.
  if (ModuleFile *ModuleEntry = lookup(*FileKey)) {
    if (isModuleFileOutOfDate(ModuleEntry->Size, ModuleEntry->ModTime,
                              ExpectedSize, ExpectedModTime, Result)) {
      Result.setOutOfDate(ModuleEntry->InputFilesValidationStatus);
      return Result;
    }

    // Check the stored signature.
    if (checkSignature(ModuleEntry->Signature, ExpectedSignature, Result)) {
      Result.setOutOfDate(ModuleEntry->InputFilesValidationStatus);
      return Result;
    }

    Result.Module = ModuleEntry;
    updateModuleImports(*ModuleEntry, ImportedBy, ImportLoc);
    Result.K = AddModuleResult::AlreadyLoaded;
    return Result;
  }

  // Load the contents of the module
  off_t Size = ExpectedSize;
  time_t ModTime = ExpectedModTime;
  llvm::MemoryBuffer *ModuleBuffer = nullptr;
  std::unique_ptr<llvm::MemoryBuffer> NewFileBuffer = nullptr;
  if (llvm::MemoryBuffer *Buffer =
          getModuleCache().getInMemoryModuleCache().lookupPCM(FileName, Size,
                                                              ModTime)) {
    ModuleBuffer = Buffer;
  } else if (getModuleCache().getInMemoryModuleCache().shouldBuildPCM(
                 FileName)) {
    // Report that the module is out of date, since we tried (and failed) to
    // import it earlier. No ModuleFile exists yet, so derive the validation
    // status from the module kind being loaded.
    Result.setOutOfDate(Type == MK_ExplicitModule || Type == MK_PrebuiltModule
                            ? InputFilesValidation::Disabled
                            : InputFilesValidation::NotStarted);
    return Result;
  } else {
    auto Buf = [&]() -> Expected<std::unique_ptr<llvm::MemoryBuffer>> {
      assert(!FileName.isInMemory() && "In-memory module not found");

      // Implicit modules live in the module cache.
      if (FileName.getImplicitModuleSuffixLength())
        return ModCache.read(FileName, Size, ModTime);

      // Explicit modules are treated as any other compiler input file, load
      // them via FileManager.
      Expected<FileEntryRef> Entry =
          FileName == StringRef("-")
              ? FileMgr.getSTDIN()
              : FileMgr.getFileRef(FileName, /*OpenFile=*/true,
                                   /*CacheFailure=*/true,
                                   /*IsText=*/false);
      if (!Entry)
        return Entry.takeError();

      Size = Entry->getSize();
      ModTime = Entry->getModificationTime();

      // RequiresNullTerminator is false because module files don't need it, and
      // this allows the file to still be mmapped.
      return llvm::errorOrToExpected(
          FileMgr.getBufferForFile(*Entry, /*IsVolatile=*/false,
                                   /*RequiresNullTerminator=*/false,
                                   /*MaybeLimit=*/std::nullopt,
                                   /*IsText=*/false));
    }();

    if (!Buf) {
      Result.BufferError = llvm::toString(Buf.takeError());
      Result.K = AddModuleResult::Missing;
      return Result;
    }

    NewFileBuffer = std::move(*Buf);
    ModuleBuffer = NewFileBuffer.get();
  }

  // Allocate bookkeeping for a module file not yet loaded into this reader.
  auto NewModule = std::make_unique<ModuleFile>(Type, *FileKey, Generation);
  NewModule->Index = Chain.size();
  NewModule->FileName = FileName;
  NewModule->ImportLoc = ImportLoc;
  NewModule->InputFilesValidationTimestamp = InputFilesValidationTimestamp;
  NewModule->Size = Size;
  NewModule->ModTime = ModTime;
  NewModule->Buffer = ModuleBuffer;
  // Initialize the stream.
  NewModule->Data = PCHContainerRdr.ExtractPCH(*NewModule->Buffer);

  // Check file properties.
  if (isModuleFileOutOfDate(Size, ModTime, ExpectedSize, ExpectedModTime,
                            Result)) {
    Result.setOutOfDate(NewModule->InputFilesValidationStatus);
    return Result;
  }

  // Read the signature eagerly now so that we can check it.  Avoid calling
  // ReadSignature unless there's something to check though.
  if (ExpectedSignature && checkSignature(ReadSignature(NewModule->Data),
                                          ExpectedSignature, Result)) {
    Result.setOutOfDate(NewModule->InputFilesValidationStatus);
    return Result;
  }

  if (NewFileBuffer)
    getModuleCache().getInMemoryModuleCache().addPCM(
        FileName, std::move(NewFileBuffer), Size, ModTime);

  // We're keeping this module. Store it in the map.
  Result.Module = Modules[*FileKey] = NewModule.get();

  updateModuleImports(*NewModule, ImportedBy, ImportLoc);

  if (!NewModule->isModule())
    PCHChain.push_back(NewModule.get());
  if (!ImportedBy)
    Roots.push_back(NewModule.get());

  Chain.push_back(std::move(NewModule));
  Result.K = AddModuleResult::NewlyLoaded;
  return Result;
}

void ModuleManager::removeModules(ModuleIterator First) {
  auto Last = end();
  if (First == Last)
    return;

  // Explicitly clear VisitOrder since we might not notice it is stale.
  VisitOrder.clear();

  // Collect the set of module file pointers that we'll be removing.
  llvm::SmallPtrSet<ModuleFile *, 4> victimSet(
      (llvm::pointer_iterator<ModuleIterator>(First)),
      (llvm::pointer_iterator<ModuleIterator>(Last)));

  auto IsVictim = [&](ModuleFile *MF) {
    return victimSet.count(MF);
  };
  // Remove any references to the now-destroyed modules.
  for (auto I = begin(); I != First; ++I) {
    I->Imports.remove_if(IsVictim);
    I->ImportedBy.remove_if(IsVictim);
  }
  llvm::erase_if(Roots, IsVictim);

  // Remove the modules from the PCH chain.
  for (auto I = First; I != Last; ++I) {
    if (!I->isModule()) {
      PCHChain.erase(llvm::find(PCHChain, &*I), PCHChain.end());
      break;
    }
  }

  // Delete the modules.
  for (ModuleIterator victim = First; victim != Last; ++victim)
    Modules.erase(victim->FileKey);

  Chain.erase(Chain.begin() + (First - begin()), Chain.end());
}

std::unique_ptr<ModuleManager::VisitState> ModuleManager::allocateVisitState() {
  // Fast path: if we have a cached state, use it.
  if (FirstVisitState) {
    auto Result = std::move(FirstVisitState);
    FirstVisitState = std::move(Result->NextState);
    return Result;
  }

  // Allocate and return a new state.
  return std::make_unique<VisitState>(size());
}

void ModuleManager::returnVisitState(std::unique_ptr<VisitState> State) {
  assert(State->NextState == nullptr && "Visited state is in list?");
  State->NextState = std::move(FirstVisitState);
  FirstVisitState = std::move(State);
}

void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) {
  GlobalIndex = Index;
  if (!GlobalIndex) {
    ModulesInCommonWithGlobalIndex.clear();
    return;
  }

  // Notify the global module index about all of the modules we've already
  // loaded.
  for (ModuleFile &M : *this)
    if (!GlobalIndex->loadedModuleFile(&M))
      ModulesInCommonWithGlobalIndex.push_back(&M);
}

void ModuleManager::moduleFileAccepted(ModuleFile *MF) {
  if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
    return;

  ModulesInCommonWithGlobalIndex.push_back(MF);
}

ModuleManager::ModuleManager(FileManager &FileMgr, ModuleCache &ModCache,
                             const PCHContainerReader &PCHContainerRdr,
                             const HeaderSearch &HeaderSearchInfo)
    : FileMgr(FileMgr), ModCache(ModCache), PCHContainerRdr(PCHContainerRdr),
      HeaderSearchInfo(HeaderSearchInfo) {}

void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
                          llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
  // If the visitation order vector is the wrong size, recompute the order.
  if (VisitOrder.size() != Chain.size()) {
    unsigned N = size();
    VisitOrder.clear();
    VisitOrder.reserve(N);

    // Record the number of incoming edges for each module. When we
    // encounter a module with no incoming edges, push it into the queue
    // to seed the queue.
    SmallVector<ModuleFile *, 4> Queue;
    Queue.reserve(N);
    llvm::SmallVector<unsigned, 4> UnusedIncomingEdges;
    UnusedIncomingEdges.resize(size());
    for (ModuleFile &M : llvm::reverse(*this)) {
      unsigned Size = M.ImportedBy.size();
      UnusedIncomingEdges[M.Index] = Size;
      if (!Size)
        Queue.push_back(&M);
    }

    // Traverse the graph, making sure to visit a module before visiting any
    // of its dependencies.
    while (!Queue.empty()) {
      ModuleFile *CurrentModule = Queue.pop_back_val();
      VisitOrder.push_back(CurrentModule);

      // For any module that this module depends on, push it on the
      // stack (if it hasn't already been marked as visited).
      for (ModuleFile *M : llvm::reverse(CurrentModule->Imports)) {
        // Remove our current module as an impediment to visiting the
        // module we depend on. If we were the last unvisited module
        // that depends on this particular module, push it into the
        // queue to be visited.
        unsigned &NumUnusedEdges = UnusedIncomingEdges[M->Index];
        if (NumUnusedEdges && (--NumUnusedEdges == 0))
          Queue.push_back(M);
      }
    }

    assert(VisitOrder.size() == N && "Visitation order is wrong?");

    FirstVisitState = nullptr;
  }

  auto State = allocateVisitState();
  unsigned VisitNumber = State->NextVisitNumber++;

  // If the caller has provided us with a hit-set that came from the global
  // module index, mark every module file in common with the global module
  // index that is *not* in that set as 'visited'.
  if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
    for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
    {
      ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
      if (!ModuleFilesHit->count(M))
        State->VisitNumber[M->Index] = VisitNumber;
    }
  }

  for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
    ModuleFile *CurrentModule = VisitOrder[I];
    // Should we skip this module file?
    if (State->VisitNumber[CurrentModule->Index] == VisitNumber)
      continue;

    // Visit the module.
    assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1);
    State->VisitNumber[CurrentModule->Index] = VisitNumber;
    if (!Visitor(*CurrentModule))
      continue;

    // The visitor has requested that cut off visitation of any
    // module that the current module depends on. To indicate this
    // behavior, we mark all of the reachable modules as having been visited.
    ModuleFile *NextModule = CurrentModule;
    do {
      // For any module that this module depends on, push it on the
      // stack (if it hasn't already been marked as visited).
      for (llvm::SetVector<ModuleFile *>::iterator
             M = NextModule->Imports.begin(),
             MEnd = NextModule->Imports.end();
           M != MEnd; ++M) {
        if (State->VisitNumber[(*M)->Index] != VisitNumber) {
          State->Stack.push_back(*M);
          State->VisitNumber[(*M)->Index] = VisitNumber;
        }
      }

      if (State->Stack.empty())
        break;

      // Pop the next module off the stack.
      NextModule = State->Stack.pop_back_val();
    } while (true);
  }

  returnVisitState(std::move(State));
}

#ifndef NDEBUG
namespace llvm {

  template<>
  struct GraphTraits<ModuleManager> {
    using NodeRef = ModuleFile *;
    using ChildIteratorType = llvm::SetVector<ModuleFile *>::const_iterator;
    using nodes_iterator = pointer_iterator<ModuleManager::ModuleConstIterator>;

    static ChildIteratorType child_begin(NodeRef Node) {
      return Node->Imports.begin();
    }

    static ChildIteratorType child_end(NodeRef Node) {
      return Node->Imports.end();
    }

    static nodes_iterator nodes_begin(const ModuleManager &Manager) {
      return nodes_iterator(Manager.begin());
    }

    static nodes_iterator nodes_end(const ModuleManager &Manager) {
      return nodes_iterator(Manager.end());
    }
  };

  template<>
  struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits {
    explicit DOTGraphTraits(bool IsSimple = false)
        : DefaultDOTGraphTraits(IsSimple) {}

    static bool renderGraphFromBottomUp() { return true; }

    std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
      return M->ModuleName;
    }
  };

} // namespace llvm

void ModuleManager::viewGraph() {
  llvm::ViewGraph(*this, "Modules");
}
#endif
