diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-10-11 16:05:00 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-10-11 16:05:00 +0000 |
commit | 900ab95e12bb7483971640a91075699eec391804 (patch) | |
tree | 7c665d86bcfa0926f78ebe6f0ddb5149f0db9035 /lib/Frontend/ASTUnit.cpp | |
parent | 50d2b268d7a49719fe9dae89195ff809c4572dbf (diff) |
[libclang] Improve AST serialization done by ASTUnit::Save().
The ASTUnit needs to initialize an ASTWriter at the beginning of
parsing to fully handle serialization of a translation unit that
imports modules. Do this by introducing an option to enable it, which
corresponds to CXTranslationUnit_ForSerialization on the C API side.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165717 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/ASTUnit.cpp')
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 92 |
1 files changed, 64 insertions, 28 deletions
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 6a4f0eb6d7..9954705d39 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -180,6 +180,14 @@ void OnDiskData::Cleanup() { CleanPreambleFile(); } +struct ASTUnit::ASTWriterData { + SmallString<128> Buffer; + llvm::BitstreamWriter Stream; + ASTWriter Writer; + + ASTWriterData() : Stream(Buffer), Writer(Stream) { } +}; + void ASTUnit::clearFileLevelDecls() { for (FileDeclsTy::iterator I = FileDecls.begin(), E = FileDecls.end(); I != E; ++I) @@ -514,29 +522,26 @@ public: virtual bool ReadLanguageOptions(const serialization::ModuleFile &M, const LangOptions &LangOpts) { - if (InitializedLanguage || M.Kind != serialization::MK_MainFile) + if (InitializedLanguage) return false; + assert(M.Kind == serialization::MK_MainFile); + LangOpt = LangOpts; - - // Initialize the preprocessor. - PP.Initialize(*Target); - - // Initialize the ASTContext - Context.InitBuiltinTypes(*Target); - InitializedLanguage = true; - - applyLangOptsToTarget(); + + updated(); return false; } virtual bool ReadTargetTriple(const serialization::ModuleFile &M, StringRef Triple) { // If we've already initialized the target, don't do it again. - if (Target || M.Kind != serialization::MK_MainFile) + if (Target) return false; + assert(M.Kind == serialization::MK_MainFile); + // FIXME: This is broken, we should store the TargetOptions in the AST file. TargetOptions TargetOpts; TargetOpts.ABI = ""; @@ -546,7 +551,7 @@ public: TargetOpts.Triple = Triple; Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(), TargetOpts); - applyLangOptsToTarget(); + updated(); return false; } @@ -570,14 +575,21 @@ public: } private: - void applyLangOptsToTarget() { - if (Target && InitializedLanguage) { - // Inform the target of the language options. - // - // FIXME: We shouldn't need to do this, the target should be immutable once - // created. This complexity should be lifted elsewhere. - Target->setForcedLangOptions(LangOpt); - } + void updated() { + if (!Target || !InitializedLanguage) + return; + + // Inform the target of the language options. + // + // FIXME: We shouldn't need to do this, the target should be immutable once + // created. This complexity should be lifted elsewhere. + Target->setForcedLangOptions(LangOpt); + + // Initialize the preprocessor. + PP.Initialize(*Target); + + // Initialize the ASTContext + Context.InitBuiltinTypes(*Target); } }; @@ -642,6 +654,12 @@ const std::string &ASTUnit::getOriginalSourceFileName() { return OriginalSourceFile; } +ASTDeserializationListener *ASTUnit::getDeserializationListener() { + if (WriterData) + return &WriterData->Writer; + return 0; +} + llvm::MemoryBuffer *ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) { assert(FileMgr); @@ -917,6 +935,10 @@ public: for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) handleTopLevelDecl(*it); } + + virtual ASTDeserializationListener *GetASTDeserializationListener() { + return Unit.getDeserializationListener(); + } }; class TopLevelDeclTrackerAction : public ASTFrontendAction { @@ -1929,6 +1951,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies, bool UserFilesAreVolatile, + bool ForSerialization, OwningPtr<ASTUnit> *ErrAST) { if (!Diags.getPtr()) { // No diagnostics engine was provided, so create our own diagnostics object @@ -1992,6 +2015,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size(); AST->StoredDiagnostics.swap(StoredDiagnostics); AST->Invocation = CI; + if (ForSerialization) + AST->WriterData.reset(new ASTWriterData()); CI = 0; // Zero out now to ease cleanup during crash recovery. // Recover resources if we crash before exiting this method. @@ -2506,20 +2531,31 @@ bool ASTUnit::Save(StringRef File) { return false; } +static bool serializeUnit(ASTWriter &Writer, + SmallVectorImpl<char> &Buffer, + Sema &S, + bool hasErrors, + raw_ostream &OS) { + Writer.WriteAST(S, 0, std::string(), 0, "", hasErrors); + + // Write the generated bitstream to "Out". + if (!Buffer.empty()) + OS.write(Buffer.data(), Buffer.size()); + + return false; +} + bool ASTUnit::serialize(raw_ostream &OS) { bool hasErrors = getDiagnostics().hasErrorOccurred(); + if (WriterData) + return serializeUnit(WriterData->Writer, WriterData->Buffer, + getSema(), hasErrors, OS); + SmallString<128> Buffer; llvm::BitstreamWriter Stream(Buffer); ASTWriter Writer(Stream); - // FIXME: Handle modules - Writer.WriteAST(getSema(), 0, std::string(), 0, "", hasErrors); - - // Write the generated bitstream to "Out". - if (!Buffer.empty()) - OS.write((char *)&Buffer.front(), Buffer.size()); - - return false; + return serializeUnit(Writer, Buffer, getSema(), hasErrors, OS); } typedef ContinuousRangeMap<unsigned, int, 2> SLocRemap; |