diff options
Diffstat (limited to 'lib/Frontend/CompilerInstance.cpp')
| -rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 57 | 
1 files changed, 42 insertions, 15 deletions
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index afcaa6e87878..8b4b16920668 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -13,6 +13,7 @@  #include "clang/AST/Decl.h"  #include "clang/Basic/Diagnostic.h"  #include "clang/Basic/FileManager.h" +#include "clang/Basic/MemoryBufferCache.h"  #include "clang/Basic/SourceManager.h"  #include "clang/Basic/TargetInfo.h"  #include "clang/Basic/Version.h" @@ -55,12 +56,15 @@ using namespace clang;  CompilerInstance::CompilerInstance(      std::shared_ptr<PCHContainerOperations> PCHContainerOps, -    bool BuildingModule) -    : ModuleLoader(BuildingModule), Invocation(new CompilerInvocation()), -      ModuleManager(nullptr), -      ThePCHContainerOperations(std::move(PCHContainerOps)), -      BuildGlobalModuleIndex(false), HaveFullGlobalModuleIndex(false), -      ModuleBuildFailed(false) {} +    MemoryBufferCache *SharedPCMCache) +    : ModuleLoader(/* BuildingModule = */ SharedPCMCache), +      Invocation(new CompilerInvocation()), +      PCMCache(SharedPCMCache ? SharedPCMCache : new MemoryBufferCache), +      ThePCHContainerOperations(std::move(PCHContainerOps)) { +  // Don't allow this to invalidate buffers in use by others. +  if (SharedPCMCache) +    getPCMCache().finalizeCurrentBuffers(); +}  CompilerInstance::~CompilerInstance() {    assert(OutputFiles.empty() && "Still output files in flight?"); @@ -131,6 +135,8 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::getModuleManager() const {    return ModuleManager;  }  void CompilerInstance::setModuleManager(IntrusiveRefCntPtr<ASTReader> Reader) { +  assert(PCMCache.get() == &Reader->getModuleManager().getPCMCache() && +         "Expected ASTReader to use the same PCM cache");    ModuleManager = std::move(Reader);  } @@ -373,7 +379,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {                         getDiagnostics(), getLangOpts(), &getTarget());    PP = std::make_shared<Preprocessor>(        Invocation->getPreprocessorOptsPtr(), getDiagnostics(), getLangOpts(), -      getSourceManager(), *HeaderInfo, *this, PTHMgr, +      getSourceManager(), getPCMCache(), *HeaderInfo, *this, PTHMgr,        /*OwnsHeaderSearch=*/true, TUKind);    PP->Initialize(getTarget(), getAuxTarget()); @@ -491,6 +497,8 @@ void CompilerInstance::createPCHExternalASTSource(        AllowPCHWithCompilerErrors, getPreprocessor(), getASTContext(),        getPCHContainerReader(),        getFrontendOpts().ModuleFileExtensions, +      TheDependencyFileGenerator.get(), +      DependencyCollectors,        DeserializationListener,        OwnDeserializationListener, Preamble,        getFrontendOpts().UseGlobalModuleIndex); @@ -501,6 +509,8 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(      bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context,      const PCHContainerReader &PCHContainerRdr,      ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, +    DependencyFileGenerator *DependencyFile, +    ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors,      void *DeserializationListener, bool OwnDeserializationListener,      bool Preamble, bool UseGlobalModuleIndex) {    HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); @@ -518,6 +528,12 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(    Reader->setDeserializationListener(        static_cast<ASTDeserializationListener *>(DeserializationListener),        /*TakeOwnership=*/OwnDeserializationListener); + +  if (DependencyFile) +    DependencyFile->AttachToASTReader(*Reader); +  for (auto &Listener : DependencyCollectors) +    Listener->attachToASTReader(*Reader); +    switch (Reader->ReadAST(Path,                            Preamble ? serialization::MK_Preamble                                     : serialization::MK_PCH, @@ -1032,7 +1048,7 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,    // Remove any macro definitions that are explicitly ignored by the module.    // They aren't supposed to affect how the module is built anyway. -  const HeaderSearchOptions &HSOpts = Invocation->getHeaderSearchOpts(); +  HeaderSearchOptions &HSOpts = Invocation->getHeaderSearchOpts();    PPOpts.Macros.erase(        std::remove_if(PPOpts.Macros.begin(), PPOpts.Macros.end(),                       [&HSOpts](const std::pair<std::string, bool> &def) { @@ -1063,6 +1079,8 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,    FrontendOpts.DisableFree = false;    FrontendOpts.GenerateGlobalModuleIndex = false;    FrontendOpts.BuildingImplicitModule = true; +  // Force implicitly-built modules to hash the content of the module file. +  HSOpts.ModulesHashContent = true;    FrontendOpts.Inputs.clear();    InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts()); @@ -1074,9 +1092,11 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,           Invocation->getModuleHash() && "Module hash mismatch!");    // Construct a compiler instance that will be used to actually create the -  // module. +  // module.  Since we're sharing a PCMCache, +  // CompilerInstance::CompilerInstance is responsible for finalizing the +  // buffers to prevent use-after-frees.    CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(), -                            /*BuildingModule=*/true); +                            &ImportingInstance.getPreprocessor().getPCMCache());    auto &Inv = *Invocation;    Instance.setInvocation(std::move(Invocation)); @@ -1180,10 +1200,14 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,      llvm::LockFileManager Locked(ModuleFileName);      switch (Locked) {      case llvm::LockFileManager::LFS_Error: -      Diags.Report(ModuleNameLoc, diag::err_module_lock_failure) +      // PCMCache takes care of correctness and locks are only necessary for +      // performance. Fallback to building the module in case of any lock +      // related errors. +      Diags.Report(ModuleNameLoc, diag::remark_module_lock_failure)            << Module->Name << Locked.getErrorMessage(); -      return false; - +      // Clear out any potential leftover. +      Locked.unsafeRemoveLockFile(); +      // FALLTHROUGH      case llvm::LockFileManager::LFS_Owned:        // We're responsible for building the module ourselves.        if (!compileModuleImpl(ImportingInstance, ModuleNameLoc, Module, @@ -1203,11 +1227,14 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,        case llvm::LockFileManager::Res_OwnerDied:          continue; // try again to get the lock.        case llvm::LockFileManager::Res_Timeout: -        Diags.Report(ModuleNameLoc, diag::err_module_lock_timeout) +        // Since PCMCache takes care of correctness, we try waiting for another +        // process to complete the build so clang does not do it done twice. If +        // case of timeout, build it ourselves. +        Diags.Report(ModuleNameLoc, diag::remark_module_lock_timeout)              << Module->Name;          // Clear the lock file so that future invokations can make progress.          Locked.unsafeRemoveLockFile(); -        return false; +        continue;        }        break;      }  | 
