diff options
Diffstat (limited to 'clang/lib/Frontend')
-rw-r--r-- | clang/lib/Frontend/ASTMerge.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Frontend/ASTUnit.cpp | 109 | ||||
-rw-r--r-- | clang/lib/Frontend/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Frontend/ChainedIncludesSource.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInstance.cpp | 56 | ||||
-rw-r--r-- | clang/lib/Frontend/FrontendAction.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Frontend/FrontendActions.cpp | 59 | ||||
-rw-r--r-- | clang/lib/Frontend/InitPreprocessor.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHContainerOperations.cpp | 70 |
9 files changed, 242 insertions, 112 deletions
diff --git a/clang/lib/Frontend/ASTMerge.cpp b/clang/lib/Frontend/ASTMerge.cpp index b84df94ef80..f6f1551b423 100644 --- a/clang/lib/Frontend/ASTMerge.cpp +++ b/clang/lib/Frontend/ASTMerge.cpp @@ -45,8 +45,10 @@ void ASTMergeAction::ExecuteAction() { new ForwardingDiagnosticConsumer( *CI.getDiagnostics().getClient()), /*ShouldOwnClient=*/true)); - std::unique_ptr<ASTUnit> Unit = ASTUnit::LoadFromASTFile( - ASTFiles[I], Diags, CI.getFileSystemOpts(), false); + std::unique_ptr<ASTUnit> Unit = + ASTUnit::LoadFromASTFile(ASTFiles[I], CI.getPCHContainerOperations(), + Diags, CI.getFileSystemOpts(), false); + if (!Unit) continue; diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 4fd330d44b7..01c56bdc4df 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -648,7 +648,9 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags, } std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( - const std::string &Filename, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + const std::string &Filename, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls, ArrayRef<RemappedFile> RemappedFiles, bool CaptureDiagnostics, bool AllowPCHWithCompilerErrors, bool UserFilesAreVolatile) { @@ -705,10 +707,10 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( bool disableValid = false; if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION")) disableValid = true; - AST->Reader = new ASTReader(PP, Context, - /*isysroot=*/"", - /*DisableValidation=*/disableValid, - AllowPCHWithCompilerErrors); + AST->Reader = new ASTReader(PP, Context, *PCHContainerOps, + /*isysroot=*/"", + /*DisableValidation=*/disableValid, + AllowPCHWithCompilerErrors); AST->Reader->setListener(llvm::make_unique<ASTInfoCollector>( *AST->PP, Context, AST->ASTFileLangOpts, AST->TargetOpts, AST->Target, @@ -916,13 +918,16 @@ class PrecompilePreambleConsumer : public PCHGenerator { unsigned &Hash; std::vector<Decl *> TopLevelDecls; PrecompilePreambleAction *Action; + raw_ostream *Out; public: PrecompilePreambleConsumer(ASTUnit &Unit, PrecompilePreambleAction *Action, const Preprocessor &PP, StringRef isysroot, raw_ostream *Out) - : PCHGenerator(PP, "", nullptr, isysroot, Out, /*AllowASTWithErrors=*/true), - Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()), Action(Action) { + : PCHGenerator(PP, "", nullptr, isysroot, std::make_shared<PCHBuffer>(), + /*AllowASTWithErrors=*/true), + Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()), Action(Action), + Out(Out) { Hash = 0; } @@ -943,6 +948,14 @@ public: void HandleTranslationUnit(ASTContext &Ctx) override { PCHGenerator::HandleTranslationUnit(Ctx); if (hasEmittedPCH()) { + // Write the generated bitstream to "Out". + *Out << getPCH(); + // Make sure it hits disk now. + Out->flush(); + // Free the buffer. + llvm::SmallVector<char, 0> Empty; + getPCH() = std::move(Empty); + // Translate the top-level declarations we captured during // parsing into declaration IDs in the precompiled // preamble. This will allow us to deserialize those top-level @@ -1015,14 +1028,16 @@ static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> & /// /// \returns True if a failure occurred that causes the ASTUnit not to /// contain any translation-unit information, false otherwise. -bool ASTUnit::Parse(std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer) { +bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, + std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer) { SavedMainFileBuffer.reset(); if (!Invocation) return true; // Create the compiler instance to use for building the AST. - std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); + std::unique_ptr<CompilerInstance> Clang( + new CompilerInstance(PCHContainerOps)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> @@ -1323,6 +1338,7 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts, /// Otherwise, returns a NULL pointer. std::unique_ptr<llvm::MemoryBuffer> ASTUnit::getMainBufferWithPrecompiledPreamble( + std::shared_ptr<PCHContainerOperations> PCHContainerOps, const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild, unsigned MaxLines) { @@ -1487,7 +1503,8 @@ ASTUnit::getMainBufferWithPrecompiledPreamble( PreprocessorOpts.PrecompiledPreambleBytes.second = false; // Create the compiler instance to use for building the precompiled preamble. - std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); + std::unique_ptr<CompilerInstance> Clang( + new CompilerInstance(PCHContainerOps)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> @@ -1702,12 +1719,13 @@ ASTUnit *ASTUnit::create(CompilerInvocation *CI, } ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( - CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, - ASTFrontendAction *Action, ASTUnit *Unit, bool Persistent, - StringRef ResourceFilesPath, bool OnlyLocalDecls, bool CaptureDiagnostics, - bool PrecompilePreamble, bool CacheCodeCompletionResults, - bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile, - std::unique_ptr<ASTUnit> *ErrAST) { + CompilerInvocation *CI, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, ASTFrontendAction *Action, + ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath, + bool OnlyLocalDecls, bool CaptureDiagnostics, bool PrecompilePreamble, + bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, + bool UserFilesAreVolatile, std::unique_ptr<ASTUnit> *ErrAST) { assert(CI && "A CompilerInvocation is required"); std::unique_ptr<ASTUnit> OwnAST; @@ -1746,7 +1764,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts()); // Create the compiler instance to use for building the AST. - std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); + std::unique_ptr<CompilerInstance> Clang( + new CompilerInstance(PCHContainerOps)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> @@ -1841,7 +1860,9 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( return AST; } -bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) { +bool ASTUnit::LoadFromCompilerInvocation( + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + bool PrecompilePreamble) { if (!Invocation) return true; @@ -1853,7 +1874,8 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) { std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; if (PrecompilePreamble) { PreambleRebuildCounter = 2; - OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation); + OverrideMainBuffer = + getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation); } SimpleTimer ParsingTimer(WantTiming); @@ -1863,12 +1885,14 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) { llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer> MemBufferCleanup(OverrideMainBuffer.get()); - return Parse(std::move(OverrideMainBuffer)); + return Parse(PCHContainerOps, std::move(OverrideMainBuffer)); } std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation( - CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, - bool OnlyLocalDecls, bool CaptureDiagnostics, bool PrecompilePreamble, + CompilerInvocation *CI, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, bool OnlyLocalDecls, + bool CaptureDiagnostics, bool PrecompilePreamble, TranslationUnitKind TUKind, bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile) { // Create the AST unit. @@ -1897,13 +1921,14 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation( llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > DiagCleanup(Diags.get()); - if (AST->LoadFromCompilerInvocation(PrecompilePreamble)) + if (AST->LoadFromCompilerInvocation(PCHContainerOps, PrecompilePreamble)) return nullptr; return AST; } ASTUnit *ASTUnit::LoadFromCommandLine( const char **ArgBegin, const char **ArgEnd, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath, bool OnlyLocalDecls, bool CaptureDiagnostics, ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName, @@ -1975,7 +2000,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine( llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> ASTUnitCleanup(AST.get()); - if (AST->LoadFromCompilerInvocation(PrecompilePreamble)) { + if (AST->LoadFromCompilerInvocation(PCHContainerOps, PrecompilePreamble)) { // Some error occurred, if caller wants to examine diagnostics, pass it the // ASTUnit. if (ErrAST) { @@ -1988,7 +2013,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine( return AST.release(); } -bool ASTUnit::Reparse(ArrayRef<RemappedFile> RemappedFiles) { +bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, + ArrayRef<RemappedFile> RemappedFiles) { if (!Invocation) return true; @@ -2012,8 +2038,9 @@ bool ASTUnit::Reparse(ArrayRef<RemappedFile> RemappedFiles) { // build a precompiled preamble, do so now. std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; if (!getPreambleFile(this).empty() || PreambleRebuildCounter > 0) - OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation); - + OverrideMainBuffer = + getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation); + // Clear out the diagnostics state. getDiagnostics().Reset(); ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); @@ -2021,7 +2048,7 @@ bool ASTUnit::Reparse(ArrayRef<RemappedFile> RemappedFiles) { getDiagnostics().setNumWarnings(NumWarningsInPreamble); // Parse the sources - bool Result = Parse(std::move(OverrideMainBuffer)); + bool Result = Parse(PCHContainerOps, std::move(OverrideMainBuffer)); // If we're caching global code-completion results, and the top-level // declarations have changed, clear out the code-completion cache. @@ -2273,18 +2300,15 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, AllResults.size()); } - - -void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column, - ArrayRef<RemappedFile> RemappedFiles, - bool IncludeMacros, - bool IncludeCodePatterns, - bool IncludeBriefComments, - CodeCompleteConsumer &Consumer, - DiagnosticsEngine &Diag, LangOptions &LangOpts, - SourceManager &SourceMgr, FileManager &FileMgr, - SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics, - SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) { +void ASTUnit::CodeComplete( + StringRef File, unsigned Line, unsigned Column, + ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros, + bool IncludeCodePatterns, bool IncludeBriefComments, + CodeCompleteConsumer &Consumer, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr, + FileManager &FileMgr, SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics, + SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) { if (!Invocation) return; @@ -2318,7 +2342,8 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column, LangOpts.SpellChecking = false; CCInvocation->getDiagnosticOpts().IgnoreWarnings = true; - std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); + std::unique_ptr<CompilerInstance> Clang( + new CompilerInstance(PCHContainerOps)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> @@ -2389,7 +2414,7 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column, if (!llvm::sys::fs::getUniqueID(MainPath, MainID)) { if (CompleteFileID == MainID && Line > 1) OverrideMainBuffer = getMainBufferWithPrecompiledPreamble( - *CCInvocation, false, Line - 1); + PCHContainerOps, *CCInvocation, false, Line - 1); } } } diff --git a/clang/lib/Frontend/CMakeLists.txt b/clang/lib/Frontend/CMakeLists.txt index 7c5fca54d1e..9a3e459640a 100644 --- a/clang/lib/Frontend/CMakeLists.txt +++ b/clang/lib/Frontend/CMakeLists.txt @@ -31,6 +31,7 @@ add_clang_library(clangFrontend LogDiagnosticPrinter.cpp ModuleDependencyCollector.cpp MultiplexConsumer.cpp + PCHContainerOperations.cpp PrintPreprocessedOutput.cpp SerializedDiagnosticPrinter.cpp SerializedDiagnosticReader.cpp diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp index f3677f8000c..be30d43a843 100644 --- a/clang/lib/Frontend/ChainedIncludesSource.cpp +++ b/clang/lib/Frontend/ChainedIncludesSource.cpp @@ -80,8 +80,9 @@ createASTReader(CompilerInstance &CI, StringRef pchFile, ASTDeserializationListener *deserialListener = nullptr) { Preprocessor &PP = CI.getPreprocessor(); std::unique_ptr<ASTReader> Reader; - Reader.reset(new ASTReader(PP, CI.getASTContext(), /*isysroot=*/"", - /*DisableValidation=*/true)); + Reader.reset(new ASTReader(PP, CI.getASTContext(), + *CI.getPCHContainerOperations(), + /*isysroot=*/"", /*DisableValidation=*/true)); for (unsigned ti = 0; ti < bufNames.size(); ++ti) { StringRef sr(bufNames[ti]); Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti])); @@ -145,7 +146,8 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource( IntrusiveRefCntPtr<DiagnosticsEngine> Diags( new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient)); - std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); + std::unique_ptr<CompilerInstance> Clang( + new CompilerInstance(CI.getPCHContainerOperations())); Clang->setInvocation(CInvok.release()); Clang->setDiagnostics(Diags.get()); Clang->setTarget(TargetInfo::CreateTargetInfo( @@ -157,11 +159,9 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource( &Clang->getPreprocessor()); Clang->createASTContext(); - SmallVector<char, 256> serialAST; - llvm::raw_svector_ostream OS(serialAST); - auto consumer = - llvm::make_unique<PCHGenerator>(Clang->getPreprocessor(), "-", nullptr, - /*isysroot=*/"", &OS); + auto Buffer = std::make_shared<PCHBuffer>(); + auto consumer = llvm::make_unique<PCHGenerator>( + Clang->getPreprocessor(), "-", nullptr, /*isysroot=*/"", Buffer); Clang->getASTContext().setASTMutationListener( consumer->GetASTMutationListener()); Clang->setASTConsumer(std::move(consumer)); @@ -198,7 +198,11 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource( ParseAST(Clang->getSema()); Clang->getDiagnosticClient().EndSourceFile(); - SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(OS.str())); + assert(Buffer->IsComplete && "serialization did not complete"); + auto &serialAST = Buffer->Data; + SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy( + StringRef(serialAST.data(), serialAST.size()))); + serialAST.clear(); source->CIs.push_back(Clang.release()); } diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index aef3905b328..6b0fed67618 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -51,12 +51,13 @@ using namespace clang; -CompilerInstance::CompilerInstance(bool BuildingModule) - : ModuleLoader(BuildingModule), - Invocation(new CompilerInvocation()), ModuleManager(nullptr), - BuildGlobalModuleIndex(false), HaveFullGlobalModuleIndex(false), - ModuleBuildFailed(false) { -} +CompilerInstance::CompilerInstance( + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + bool BuildingModule) + : ModuleLoader(BuildingModule), Invocation(new CompilerInvocation()), + ModuleManager(nullptr), ThePCHContainerOperations(PCHContainerOps), + BuildGlobalModuleIndex(false), HaveFullGlobalModuleIndex(false), + ModuleBuildFailed(false) {} CompilerInstance::~CompilerInstance() { assert(OutputFiles.empty() && "Still output files in flight?"); @@ -321,7 +322,8 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { PP->getFileManager(), PPOpts); // Predefine macros and configure the preprocessor. - InitializePreprocessor(*PP, PPOpts, getFrontendOpts()); + InitializePreprocessor(*PP, PPOpts, *getPCHContainerOperations(), + getFrontendOpts()); // Initialize the header search object. ApplyHeaderSearchOptions(PP->getHeaderSearchInfo(), getHeaderSearchOpts(), @@ -397,22 +399,24 @@ void CompilerInstance::createPCHExternalASTSource( ModuleManager = createPCHExternalASTSource( Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation, AllowPCHWithCompilerErrors, getPreprocessor(), getASTContext(), - DeserializationListener, OwnDeserializationListener, Preamble, + *getPCHContainerOperations(), DeserializationListener, + OwnDeserializationListener, Preamble, getFrontendOpts().UseGlobalModuleIndex); } IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource( StringRef Path, const std::string &Sysroot, bool DisablePCHValidation, bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, + const PCHContainerOperations &PCHContainerOps, void *DeserializationListener, bool OwnDeserializationListener, bool Preamble, bool UseGlobalModuleIndex) { HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); - IntrusiveRefCntPtr<ASTReader> Reader( - new ASTReader(PP, Context, Sysroot.empty() ? "" : Sysroot.c_str(), - DisablePCHValidation, AllowPCHWithCompilerErrors, - /*AllowConfigurationMismatch*/ false, - HSOpts.ModulesValidateSystemHeaders, UseGlobalModuleIndex)); + IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader( + PP, Context, PCHContainerOps, Sysroot.empty() ? "" : Sysroot.c_str(), + DisablePCHValidation, AllowPCHWithCompilerErrors, + /*AllowConfigurationMismatch*/ false, HSOpts.ModulesValidateSystemHeaders, + UseGlobalModuleIndex)); // We need the external source to be set up before we read the AST, because // eagerly-deserialized declarations may use it. @@ -918,7 +922,8 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, // Construct a compiler instance that will be used to actually create the // module. - CompilerInstance Instance(/*BuildingModule=*/true); + CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(), + /*BuildingModule=*/true); Instance.setInvocation(&*Invocation); Instance.createDiagnostics(new ForwardingDiagnosticConsumer( @@ -1232,13 +1237,13 @@ void CompilerInstance::createModuleManager() { HeaderSearchOptions &HSOpts = getHeaderSearchOpts(); std::string Sysroot = HSOpts.Sysroot; const PreprocessorOptions &PPOpts = getPreprocessorOpts(); - ModuleManager = new ASTReader(getPreprocessor(), *Context, - Sysroot.empty() ? "" : Sysroot.c_str(), - PPOpts.DisablePCHValidation, - /*AllowASTWithCompilerErrors=*/false, - /*AllowConfigurationMismatch=*/false, - HSOpts.ModulesValidateSystemHeaders, - getFrontendOpts().UseGlobalModuleIndex); + ModuleManager = new ASTReader( + getPreprocessor(), *Context, *getPCHContainerOperations(), + Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation, + /*AllowASTWithCompilerErrors=*/false, + /*AllowConfigurationMismatch=*/false, + HSOpts.ModulesValidateSystemHeaders, + getFrontendOpts().UseGlobalModuleIndex); if (hasASTConsumer()) { ModuleManager->setDeserializationListener( getASTConsumer().GetASTDeserializationListener()); @@ -1279,6 +1284,7 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) { ModuleFileStack.push_back(FileName); ModuleNameStack.push_back(StringRef()); if (ASTReader::readASTFileControlBlock(FileName, CI.getFileManager(), + *CI.getPCHContainerOperations(), *this)) { CI.getDiagnostics().Report( SourceLocation(), CI.getFileManager().getBufferForFile(FileName) @@ -1644,8 +1650,8 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex( llvm::sys::fs::create_directories( getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); GlobalModuleIndex::writeIndex( - getFileManager(), - getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); + getFileManager(), *getPCHContainerOperations(), + getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); ModuleManager->resetForReload(); ModuleManager->loadGlobalIndex(); GlobalIndex = ModuleManager->getGlobalIndex(); @@ -1672,8 +1678,8 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex( } if (RecreateIndex) { GlobalModuleIndex::writeIndex( - getFileManager(), - getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); + getFileManager(), *getPCHContainerOperations(), + getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); ModuleManager->resetForReload(); ModuleManager->loadGlobalIndex(); GlobalIndex = ModuleManager->getGlobalIndex(); diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 9bba75541ff..db9dd3b0988 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -191,7 +191,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); std::unique_ptr<ASTUnit> AST = - ASTUnit::LoadFromASTFile(InputFile, Diags, CI.getFileSystemOpts()); + ASTUnit::LoadFromASTFile(InputFile, CI.getPCHContainerOperations(), + Diags, CI.getFileSystemOpts()); if (!AST) goto failure; @@ -271,11 +272,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, for (llvm::sys::fs::directory_iterator Dir(DirNative, EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { // Check whether this is an acceptable AST file. - if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr, - CI.getLangOpts(), - CI.getTargetOpts(), - CI.getPreprocessorOpts(), - SpecificModuleCachePath)) { + if (ASTReader::isAcceptableASTFile( + Dir->path(), FileMgr, *CI.getPCHContainerOperations(), + CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(), + SpecificModuleCachePath)) { PPOpts.ImplicitPCHInclude = Dir->path(); Found = true; break; @@ -443,8 +443,8 @@ bool FrontendAction::Execute() { if (CI.shouldBuildGlobalModuleIndex() && CI.hasFileManager() && CI.hasPreprocessor()) { GlobalModuleIndex::writeIndex( - CI.getFileManager(), - CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); + CI.getFileManager(), *CI.getPCHContainerOperations(), + CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); } return true; diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 46cdeebfdbe..6f202a15483 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -14,6 +14,7 @@ #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Pragma.h" @@ -79,18 +80,28 @@ std::unique_ptr<ASTConsumer> GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { std::string Sysroot; std::string OutputFile; - raw_ostream *OS = + raw_pwrite_stream *OS = ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile); if (!OS) return nullptr; if (!CI.getFrontendOpts().RelocatablePCH) Sysroot.clear(); - return llvm::make_unique<PCHGenerator>(CI.getPreprocessor(), OutputFile, - nullptr, Sysroot, OS); + + auto Buffer = std::make_shared<PCHBuffer>(); + std::vector<std::unique_ptr<ASTConsumer>> Consumers; + Consumers.push_back(llvm::make_unique<PCHGenerator>( + CI.getPreprocessor(), OutputFile, nullptr, Sysroot, Buffer)); + Consumers.push_back( + CI.getPCHContainerOperations()->CreatePCHContainerGenerator( + CI.getDiagnostics(), CI.getHeaderSearchOpts(), + CI.getPreprocessorOpts(), CI.getTargetOpts(), CI.getLangOpts(), + InFile, OutputFile, OS, Buffer)); + + return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); } -raw_ostream *GeneratePCHAction::ComputeASTConsumerArguments( +raw_pwrite_stream *GeneratePCHAction::ComputeASTConsumerArguments( CompilerInstance &CI, StringRef InFile, std::string &Sysroot, std::string &OutputFile) { Sysroot = CI.getHeaderSearchOpts().Sysroot; @@ -102,7 +113,7 @@ raw_ostream *GeneratePCHAction::ComputeASTConsumerArguments( // We use createOutputFile here because this is exposed via libclang, and we // must disable the RemoveFileOnSignal behavior. // We use a temporary to avoid race conditions. - raw_ostream *OS = + raw_pwrite_stream *OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, /*RemoveFileOnSignal=*/false, InFile, /*Extension=*/"", /*useTemporary=*/true); @@ -118,13 +129,21 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { std::string Sysroot; std::string OutputFile; - raw_ostream *OS = + raw_pwrite_stream *OS = ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile); if (!OS) return nullptr; - return llvm::make_unique<PCHGenerator>(CI.getPreprocessor(), OutputFile, - Module, Sysroot, OS); + auto Buffer = std::make_shared<PCHBuffer>(); + std::vector<std::unique_ptr<ASTConsumer>> Consumers; + Consumers.push_back(llvm::make_unique<PCHGenerator>( + CI.getPreprocessor(), OutputFile, Module, Sysroot, Buffer)); + Consumers.push_back( + CI.getPCHContainerOperations()->CreatePCHContainerGenerator( + CI.getDiagnostics(), CI.getHeaderSearchOpts(), + CI.getPreprocessorOpts(), CI.getTargetOpts(), CI.getLangOpts(), + InFile, OutputFile, OS, Buffer)); + return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); } static SmallVectorImpl<char> & @@ -348,7 +367,7 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, return true; } -raw_ostream *GenerateModuleAction::ComputeASTConsumerArguments( +raw_pwrite_stream *GenerateModuleAction::ComputeASTConsumerArguments( CompilerInstance &CI, StringRef InFile, std::string &Sysroot, std::string &OutputFile) { // If no output file was provided, figure out where this module would go @@ -363,7 +382,7 @@ raw_ostream *GenerateModuleAction::ComputeASTConsumerArguments( // We use createOutputFile here because this is exposed via libclang, and we // must disable the RemoveFileOnSignal behavior. // We use a temporary to avoid race conditions. - raw_ostream *OS = + raw_pwrite_stream *OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, /*RemoveFileOnSignal=*/false, InFile, /*Extension=*/"", /*useTemporary=*/true, @@ -395,13 +414,13 @@ void VerifyPCHAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot; - std::unique_ptr<ASTReader> Reader( - new ASTReader(CI.getPreprocessor(), CI.getASTContext(), - Sysroot.empty() ? "" : Sysroot.c_str(), - /*DisableValidation*/ false, - /*AllowPCHWithCompilerErrors*/ false, - /*AllowConfigurationMismatch*/ true, - /*ValidateSystemInputs*/ true)); + std::unique_ptr<ASTReader> Reader(new ASTReader( + CI.getPreprocessor(), CI.getASTContext(), *CI.getPCHContainerOperations(), + Sysroot.empty() ? "" : Sysroot.c_str(), + /*DisableValidation*/ false, + /*AllowPCHWithCompilerErrors*/ false, + /*AllowConfigurationMismatch*/ true, + /*ValidateSystemInputs*/ true)); Reader->ReadAST(getCurrentFile(), Preamble ? serialization::MK_Preamble @@ -550,9 +569,9 @@ void DumpModuleInfoAction::ExecuteAction() { Out << "Information for module file '" << getCurrentFile() << "':\n"; DumpModuleInfoListener Listener(Out); - ASTReader::readASTFileControlBlock(getCurrentFile(), - getCompilerInstance().getFileManager(), - Listener); + ASTReader::readASTFileControlBlock( + getCurrentFile(), getCompilerInstance().getFileManager(), + *getCompilerInstance().getPCHContainerOperations(), Listener); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index dfc46f47cce..24171468f1b 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -97,10 +97,11 @@ static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP, /// \brief Add an implicit \#include using the original file used to generate /// a PCH file. static void AddImplicitIncludePCH(MacroBuilder &Builder, Preprocessor &PP, + const PCHContainerOperations &PCHContainerOps, StringRef ImplicitIncludePCH) { std::string OriginalFile = - ASTReader::getOriginalSourceFile(ImplicitIncludePCH, PP.getFileManager(), - PP.getDiagnostics()); + ASTReader::getOriginalSourceFile(ImplicitIncludePCH, PP.getFileManager(), + PCHContainerOps, PP.getDiagnostics()); if (OriginalFile.empty()) return; @@ -891,9 +892,10 @@ static void InitializePredefinedMacros(const TargetInfo &TI, /// InitializePreprocessor - Initialize the preprocessor getting it and the /// environment ready to process a single file. This returns true on error. /// -void clang::InitializePreprocessor(Preprocessor &PP, - const PreprocessorOptions &InitOpts, - const FrontendOptions &FEOpts) { +void clang::InitializePreprocessor( + Preprocessor &PP, const PreprocessorOptions &InitOpts, + const PCHContainerOperations &PCHContainerOps, + const FrontendOptions &FEOpts) { const LangOptions &LangOpts = PP.getLangOpts(); std::string PredefineBuffer; PredefineBuffer.reserve(4080); @@ -952,7 +954,8 @@ void clang::InitializePreprocessor(Preprocessor &PP, // Process -include-pch/-include-pth directives. if (!InitOpts.ImplicitPCHInclude.empty()) - AddImplicitIncludePCH(Builder, PP, InitOpts.ImplicitPCHInclude); + AddImplicitIncludePCH(Builder, PP, PCHContainerOps, + InitOpts.ImplicitPCHInclude); if (!InitOpts.ImplicitPTHInclude.empty()) AddImplicitIncludePTH(Builder, PP, InitOpts.ImplicitPTHInclude); diff --git a/clang/lib/Frontend/PCHContainerOperations.cpp b/clang/lib/Frontend/PCHContainerOperations.cpp new file mode 100644 index 00000000000..fd3278b3b14 --- /dev/null +++ b/clang/lib/Frontend/PCHContainerOperations.cpp @@ -0,0 +1,70 @@ +//===--- Frontend/PCHContainerOperations.cpp - PCH Containers ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines PCHContainerOperations and RawPCHContainerOperation. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/PCHContainerOperations.h" +#include "clang/AST/ASTConsumer.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Support/raw_ostream.h" +#include "clang/Lex/ModuleLoader.h" +using namespace clang; + +PCHContainerOperations::~PCHContainerOperations() {} + +namespace { + +/// \brief A PCHContainerGenerator that writes out the PCH to a flat file. +class PCHContainerGenerator : public ASTConsumer { + std::shared_ptr<PCHBuffer> Buffer; + raw_pwrite_stream *OS; + +public: + PCHContainerGenerator(DiagnosticsEngine &Diags, + const HeaderSearchOptions &HSO, + const PreprocessorOptions &PPO, const TargetOptions &TO, + const LangOptions &LO, const std::string &MainFileName, + const std::string &OutputFileName, + llvm::raw_pwrite_stream *OS, + std::shared_ptr<PCHBuffer> Buffer) + : Buffer(Buffer), OS(OS) {} + + virtual ~PCHContainerGenerator() {} + + void HandleTranslationUnit(ASTContext &Ctx) override { + if (Buffer->IsComplete) { + // Make sure it hits disk now. + *OS << Buffer->Data; + OS->flush(); + } + // Free the space of the temporary buffer. + llvm::SmallVector<char, 0> Empty; + Buffer->Data = std::move(Empty); + } +}; +} + +std::unique_ptr<ASTConsumer> +RawPCHContainerOperations::CreatePCHContainerGenerator( + DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO, + const PreprocessorOptions &PPO, const TargetOptions &TO, + const LangOptions &LO, const std::string &MainFileName, + const std::string &OutputFileName, llvm::raw_pwrite_stream *OS, + std::shared_ptr<PCHBuffer> Buffer) const { + return llvm::make_unique<PCHContainerGenerator>( + Diags, HSO, PPO, TO, LO, MainFileName, OutputFileName, OS, Buffer); +} + +void RawPCHContainerOperations::ExtractPCH( + llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const { + StreamFile.init((const unsigned char *)Buffer.getBufferStart(), + (const unsigned char *)Buffer.getBufferEnd()); +} |