1*67e74705SXin Li //===- ChainedIncludesSource.cpp - Chained PCHs in Memory -------*- C++ -*-===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This file defines the ChainedIncludesSource class, which converts headers
11*67e74705SXin Li // to chained PCHs in memory, mainly used for testing.
12*67e74705SXin Li //
13*67e74705SXin Li //===----------------------------------------------------------------------===//
14*67e74705SXin Li
15*67e74705SXin Li #include "clang/Basic/TargetInfo.h"
16*67e74705SXin Li #include "clang/Frontend/ASTUnit.h"
17*67e74705SXin Li #include "clang/Frontend/CompilerInstance.h"
18*67e74705SXin Li #include "clang/Frontend/TextDiagnosticPrinter.h"
19*67e74705SXin Li #include "clang/Lex/Preprocessor.h"
20*67e74705SXin Li #include "clang/Parse/ParseAST.h"
21*67e74705SXin Li #include "clang/Serialization/ASTReader.h"
22*67e74705SXin Li #include "clang/Serialization/ASTWriter.h"
23*67e74705SXin Li #include "llvm/Support/MemoryBuffer.h"
24*67e74705SXin Li
25*67e74705SXin Li using namespace clang;
26*67e74705SXin Li
27*67e74705SXin Li namespace {
28*67e74705SXin Li class ChainedIncludesSource : public ExternalSemaSource {
29*67e74705SXin Li public:
30*67e74705SXin Li ~ChainedIncludesSource() override;
31*67e74705SXin Li
getFinalReader() const32*67e74705SXin Li ExternalSemaSource &getFinalReader() const { return *FinalReader; }
33*67e74705SXin Li
34*67e74705SXin Li std::vector<CompilerInstance *> CIs;
35*67e74705SXin Li IntrusiveRefCntPtr<ExternalSemaSource> FinalReader;
36*67e74705SXin Li
37*67e74705SXin Li protected:
38*67e74705SXin Li //===----------------------------------------------------------------------===//
39*67e74705SXin Li // ExternalASTSource interface.
40*67e74705SXin Li //===----------------------------------------------------------------------===//
41*67e74705SXin Li
42*67e74705SXin Li Decl *GetExternalDecl(uint32_t ID) override;
43*67e74705SXin Li Selector GetExternalSelector(uint32_t ID) override;
44*67e74705SXin Li uint32_t GetNumExternalSelectors() override;
45*67e74705SXin Li Stmt *GetExternalDeclStmt(uint64_t Offset) override;
46*67e74705SXin Li CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
47*67e74705SXin Li CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
48*67e74705SXin Li bool FindExternalVisibleDeclsByName(const DeclContext *DC,
49*67e74705SXin Li DeclarationName Name) override;
50*67e74705SXin Li void
51*67e74705SXin Li FindExternalLexicalDecls(const DeclContext *DC,
52*67e74705SXin Li llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
53*67e74705SXin Li SmallVectorImpl<Decl *> &Result) override;
54*67e74705SXin Li void CompleteType(TagDecl *Tag) override;
55*67e74705SXin Li void CompleteType(ObjCInterfaceDecl *Class) override;
56*67e74705SXin Li void StartedDeserializing() override;
57*67e74705SXin Li void FinishedDeserializing() override;
58*67e74705SXin Li void StartTranslationUnit(ASTConsumer *Consumer) override;
59*67e74705SXin Li void PrintStats() override;
60*67e74705SXin Li
61*67e74705SXin Li /// Return the amount of memory used by memory buffers, breaking down
62*67e74705SXin Li /// by heap-backed versus mmap'ed memory.
63*67e74705SXin Li void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override;
64*67e74705SXin Li
65*67e74705SXin Li //===----------------------------------------------------------------------===//
66*67e74705SXin Li // ExternalSemaSource interface.
67*67e74705SXin Li //===----------------------------------------------------------------------===//
68*67e74705SXin Li
69*67e74705SXin Li void InitializeSema(Sema &S) override;
70*67e74705SXin Li void ForgetSema() override;
71*67e74705SXin Li void ReadMethodPool(Selector Sel) override;
72*67e74705SXin Li bool LookupUnqualified(LookupResult &R, Scope *S) override;
73*67e74705SXin Li };
74*67e74705SXin Li }
75*67e74705SXin Li
76*67e74705SXin Li static ASTReader *
createASTReader(CompilerInstance & CI,StringRef pchFile,SmallVectorImpl<std::unique_ptr<llvm::MemoryBuffer>> & MemBufs,SmallVectorImpl<std::string> & bufNames,ASTDeserializationListener * deserialListener=nullptr)77*67e74705SXin Li createASTReader(CompilerInstance &CI, StringRef pchFile,
78*67e74705SXin Li SmallVectorImpl<std::unique_ptr<llvm::MemoryBuffer>> &MemBufs,
79*67e74705SXin Li SmallVectorImpl<std::string> &bufNames,
80*67e74705SXin Li ASTDeserializationListener *deserialListener = nullptr) {
81*67e74705SXin Li Preprocessor &PP = CI.getPreprocessor();
82*67e74705SXin Li std::unique_ptr<ASTReader> Reader;
83*67e74705SXin Li Reader.reset(new ASTReader(PP, CI.getASTContext(),
84*67e74705SXin Li CI.getPCHContainerReader(),
85*67e74705SXin Li /*Extensions=*/{ },
86*67e74705SXin Li /*isysroot=*/"", /*DisableValidation=*/true));
87*67e74705SXin Li for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
88*67e74705SXin Li StringRef sr(bufNames[ti]);
89*67e74705SXin Li Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti]));
90*67e74705SXin Li }
91*67e74705SXin Li Reader->setDeserializationListener(deserialListener);
92*67e74705SXin Li switch (Reader->ReadAST(pchFile, serialization::MK_PCH, SourceLocation(),
93*67e74705SXin Li ASTReader::ARR_None)) {
94*67e74705SXin Li case ASTReader::Success:
95*67e74705SXin Li // Set the predefines buffer as suggested by the PCH reader.
96*67e74705SXin Li PP.setPredefines(Reader->getSuggestedPredefines());
97*67e74705SXin Li return Reader.release();
98*67e74705SXin Li
99*67e74705SXin Li case ASTReader::Failure:
100*67e74705SXin Li case ASTReader::Missing:
101*67e74705SXin Li case ASTReader::OutOfDate:
102*67e74705SXin Li case ASTReader::VersionMismatch:
103*67e74705SXin Li case ASTReader::ConfigurationMismatch:
104*67e74705SXin Li case ASTReader::HadErrors:
105*67e74705SXin Li break;
106*67e74705SXin Li }
107*67e74705SXin Li return nullptr;
108*67e74705SXin Li }
109*67e74705SXin Li
~ChainedIncludesSource()110*67e74705SXin Li ChainedIncludesSource::~ChainedIncludesSource() {
111*67e74705SXin Li for (unsigned i = 0, e = CIs.size(); i != e; ++i)
112*67e74705SXin Li delete CIs[i];
113*67e74705SXin Li }
114*67e74705SXin Li
createChainedIncludesSource(CompilerInstance & CI,IntrusiveRefCntPtr<ExternalSemaSource> & Reader)115*67e74705SXin Li IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
116*67e74705SXin Li CompilerInstance &CI, IntrusiveRefCntPtr<ExternalSemaSource> &Reader) {
117*67e74705SXin Li
118*67e74705SXin Li std::vector<std::string> &includes = CI.getPreprocessorOpts().ChainedIncludes;
119*67e74705SXin Li assert(!includes.empty() && "No '-chain-include' in options!");
120*67e74705SXin Li
121*67e74705SXin Li IntrusiveRefCntPtr<ChainedIncludesSource> source(new ChainedIncludesSource());
122*67e74705SXin Li InputKind IK = CI.getFrontendOpts().Inputs[0].getKind();
123*67e74705SXin Li
124*67e74705SXin Li SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 4> SerialBufs;
125*67e74705SXin Li SmallVector<std::string, 4> serialBufNames;
126*67e74705SXin Li
127*67e74705SXin Li for (unsigned i = 0, e = includes.size(); i != e; ++i) {
128*67e74705SXin Li bool firstInclude = (i == 0);
129*67e74705SXin Li std::unique_ptr<CompilerInvocation> CInvok;
130*67e74705SXin Li CInvok.reset(new CompilerInvocation(CI.getInvocation()));
131*67e74705SXin Li
132*67e74705SXin Li CInvok->getPreprocessorOpts().ChainedIncludes.clear();
133*67e74705SXin Li CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear();
134*67e74705SXin Li CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
135*67e74705SXin Li CInvok->getPreprocessorOpts().DisablePCHValidation = true;
136*67e74705SXin Li CInvok->getPreprocessorOpts().Includes.clear();
137*67e74705SXin Li CInvok->getPreprocessorOpts().MacroIncludes.clear();
138*67e74705SXin Li CInvok->getPreprocessorOpts().Macros.clear();
139*67e74705SXin Li
140*67e74705SXin Li CInvok->getFrontendOpts().Inputs.clear();
141*67e74705SXin Li FrontendInputFile InputFile(includes[i], IK);
142*67e74705SXin Li CInvok->getFrontendOpts().Inputs.push_back(InputFile);
143*67e74705SXin Li
144*67e74705SXin Li TextDiagnosticPrinter *DiagClient =
145*67e74705SXin Li new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions());
146*67e74705SXin Li IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
147*67e74705SXin Li IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
148*67e74705SXin Li new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient));
149*67e74705SXin Li
150*67e74705SXin Li std::unique_ptr<CompilerInstance> Clang(
151*67e74705SXin Li new CompilerInstance(CI.getPCHContainerOperations()));
152*67e74705SXin Li Clang->setInvocation(CInvok.release());
153*67e74705SXin Li Clang->setDiagnostics(Diags.get());
154*67e74705SXin Li Clang->setTarget(TargetInfo::CreateTargetInfo(
155*67e74705SXin Li Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
156*67e74705SXin Li Clang->createFileManager();
157*67e74705SXin Li Clang->createSourceManager(Clang->getFileManager());
158*67e74705SXin Li Clang->createPreprocessor(TU_Prefix);
159*67e74705SXin Li Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(),
160*67e74705SXin Li &Clang->getPreprocessor());
161*67e74705SXin Li Clang->createASTContext();
162*67e74705SXin Li
163*67e74705SXin Li auto Buffer = std::make_shared<PCHBuffer>();
164*67e74705SXin Li ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions;
165*67e74705SXin Li auto consumer = llvm::make_unique<PCHGenerator>(
166*67e74705SXin Li Clang->getPreprocessor(), "-", nullptr, /*isysroot=*/"", Buffer,
167*67e74705SXin Li Extensions, /*AllowASTWithErrors=*/true);
168*67e74705SXin Li Clang->getASTContext().setASTMutationListener(
169*67e74705SXin Li consumer->GetASTMutationListener());
170*67e74705SXin Li Clang->setASTConsumer(std::move(consumer));
171*67e74705SXin Li Clang->createSema(TU_Prefix, nullptr);
172*67e74705SXin Li
173*67e74705SXin Li if (firstInclude) {
174*67e74705SXin Li Preprocessor &PP = Clang->getPreprocessor();
175*67e74705SXin Li PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),
176*67e74705SXin Li PP.getLangOpts());
177*67e74705SXin Li } else {
178*67e74705SXin Li assert(!SerialBufs.empty());
179*67e74705SXin Li SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 4> Bufs;
180*67e74705SXin Li // TODO: Pass through the existing MemoryBuffer instances instead of
181*67e74705SXin Li // allocating new ones.
182*67e74705SXin Li for (auto &SB : SerialBufs)
183*67e74705SXin Li Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(SB->getBuffer()));
184*67e74705SXin Li std::string pchName = includes[i-1];
185*67e74705SXin Li llvm::raw_string_ostream os(pchName);
186*67e74705SXin Li os << ".pch" << i-1;
187*67e74705SXin Li serialBufNames.push_back(os.str());
188*67e74705SXin Li
189*67e74705SXin Li IntrusiveRefCntPtr<ASTReader> Reader;
190*67e74705SXin Li Reader = createASTReader(
191*67e74705SXin Li *Clang, pchName, Bufs, serialBufNames,
192*67e74705SXin Li Clang->getASTConsumer().GetASTDeserializationListener());
193*67e74705SXin Li if (!Reader)
194*67e74705SXin Li return nullptr;
195*67e74705SXin Li Clang->setModuleManager(Reader);
196*67e74705SXin Li Clang->getASTContext().setExternalSource(Reader);
197*67e74705SXin Li }
198*67e74705SXin Li
199*67e74705SXin Li if (!Clang->InitializeSourceManager(InputFile))
200*67e74705SXin Li return nullptr;
201*67e74705SXin Li
202*67e74705SXin Li ParseAST(Clang->getSema());
203*67e74705SXin Li Clang->getDiagnosticClient().EndSourceFile();
204*67e74705SXin Li assert(Buffer->IsComplete && "serialization did not complete");
205*67e74705SXin Li auto &serialAST = Buffer->Data;
206*67e74705SXin Li SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(
207*67e74705SXin Li StringRef(serialAST.data(), serialAST.size())));
208*67e74705SXin Li serialAST.clear();
209*67e74705SXin Li source->CIs.push_back(Clang.release());
210*67e74705SXin Li }
211*67e74705SXin Li
212*67e74705SXin Li assert(!SerialBufs.empty());
213*67e74705SXin Li std::string pchName = includes.back() + ".pch-final";
214*67e74705SXin Li serialBufNames.push_back(pchName);
215*67e74705SXin Li Reader = createASTReader(CI, pchName, SerialBufs, serialBufNames);
216*67e74705SXin Li if (!Reader)
217*67e74705SXin Li return nullptr;
218*67e74705SXin Li
219*67e74705SXin Li source->FinalReader = Reader;
220*67e74705SXin Li return source;
221*67e74705SXin Li }
222*67e74705SXin Li
223*67e74705SXin Li //===----------------------------------------------------------------------===//
224*67e74705SXin Li // ExternalASTSource interface.
225*67e74705SXin Li //===----------------------------------------------------------------------===//
226*67e74705SXin Li
GetExternalDecl(uint32_t ID)227*67e74705SXin Li Decl *ChainedIncludesSource::GetExternalDecl(uint32_t ID) {
228*67e74705SXin Li return getFinalReader().GetExternalDecl(ID);
229*67e74705SXin Li }
GetExternalSelector(uint32_t ID)230*67e74705SXin Li Selector ChainedIncludesSource::GetExternalSelector(uint32_t ID) {
231*67e74705SXin Li return getFinalReader().GetExternalSelector(ID);
232*67e74705SXin Li }
GetNumExternalSelectors()233*67e74705SXin Li uint32_t ChainedIncludesSource::GetNumExternalSelectors() {
234*67e74705SXin Li return getFinalReader().GetNumExternalSelectors();
235*67e74705SXin Li }
GetExternalDeclStmt(uint64_t Offset)236*67e74705SXin Li Stmt *ChainedIncludesSource::GetExternalDeclStmt(uint64_t Offset) {
237*67e74705SXin Li return getFinalReader().GetExternalDeclStmt(Offset);
238*67e74705SXin Li }
239*67e74705SXin Li CXXBaseSpecifier *
GetExternalCXXBaseSpecifiers(uint64_t Offset)240*67e74705SXin Li ChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
241*67e74705SXin Li return getFinalReader().GetExternalCXXBaseSpecifiers(Offset);
242*67e74705SXin Li }
243*67e74705SXin Li CXXCtorInitializer **
GetExternalCXXCtorInitializers(uint64_t Offset)244*67e74705SXin Li ChainedIncludesSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
245*67e74705SXin Li return getFinalReader().GetExternalCXXCtorInitializers(Offset);
246*67e74705SXin Li }
247*67e74705SXin Li bool
FindExternalVisibleDeclsByName(const DeclContext * DC,DeclarationName Name)248*67e74705SXin Li ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
249*67e74705SXin Li DeclarationName Name) {
250*67e74705SXin Li return getFinalReader().FindExternalVisibleDeclsByName(DC, Name);
251*67e74705SXin Li }
FindExternalLexicalDecls(const DeclContext * DC,llvm::function_ref<bool (Decl::Kind)> IsKindWeWant,SmallVectorImpl<Decl * > & Result)252*67e74705SXin Li void ChainedIncludesSource::FindExternalLexicalDecls(
253*67e74705SXin Li const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
254*67e74705SXin Li SmallVectorImpl<Decl *> &Result) {
255*67e74705SXin Li return getFinalReader().FindExternalLexicalDecls(DC, IsKindWeWant, Result);
256*67e74705SXin Li }
CompleteType(TagDecl * Tag)257*67e74705SXin Li void ChainedIncludesSource::CompleteType(TagDecl *Tag) {
258*67e74705SXin Li return getFinalReader().CompleteType(Tag);
259*67e74705SXin Li }
CompleteType(ObjCInterfaceDecl * Class)260*67e74705SXin Li void ChainedIncludesSource::CompleteType(ObjCInterfaceDecl *Class) {
261*67e74705SXin Li return getFinalReader().CompleteType(Class);
262*67e74705SXin Li }
StartedDeserializing()263*67e74705SXin Li void ChainedIncludesSource::StartedDeserializing() {
264*67e74705SXin Li return getFinalReader().StartedDeserializing();
265*67e74705SXin Li }
FinishedDeserializing()266*67e74705SXin Li void ChainedIncludesSource::FinishedDeserializing() {
267*67e74705SXin Li return getFinalReader().FinishedDeserializing();
268*67e74705SXin Li }
StartTranslationUnit(ASTConsumer * Consumer)269*67e74705SXin Li void ChainedIncludesSource::StartTranslationUnit(ASTConsumer *Consumer) {
270*67e74705SXin Li return getFinalReader().StartTranslationUnit(Consumer);
271*67e74705SXin Li }
PrintStats()272*67e74705SXin Li void ChainedIncludesSource::PrintStats() {
273*67e74705SXin Li return getFinalReader().PrintStats();
274*67e74705SXin Li }
getMemoryBufferSizes(MemoryBufferSizes & sizes) const275*67e74705SXin Li void ChainedIncludesSource::getMemoryBufferSizes(MemoryBufferSizes &sizes)const{
276*67e74705SXin Li for (unsigned i = 0, e = CIs.size(); i != e; ++i) {
277*67e74705SXin Li if (const ExternalASTSource *eSrc =
278*67e74705SXin Li CIs[i]->getASTContext().getExternalSource()) {
279*67e74705SXin Li eSrc->getMemoryBufferSizes(sizes);
280*67e74705SXin Li }
281*67e74705SXin Li }
282*67e74705SXin Li
283*67e74705SXin Li getFinalReader().getMemoryBufferSizes(sizes);
284*67e74705SXin Li }
285*67e74705SXin Li
InitializeSema(Sema & S)286*67e74705SXin Li void ChainedIncludesSource::InitializeSema(Sema &S) {
287*67e74705SXin Li return getFinalReader().InitializeSema(S);
288*67e74705SXin Li }
ForgetSema()289*67e74705SXin Li void ChainedIncludesSource::ForgetSema() {
290*67e74705SXin Li return getFinalReader().ForgetSema();
291*67e74705SXin Li }
ReadMethodPool(Selector Sel)292*67e74705SXin Li void ChainedIncludesSource::ReadMethodPool(Selector Sel) {
293*67e74705SXin Li getFinalReader().ReadMethodPool(Sel);
294*67e74705SXin Li }
LookupUnqualified(LookupResult & R,Scope * S)295*67e74705SXin Li bool ChainedIncludesSource::LookupUnqualified(LookupResult &R, Scope *S) {
296*67e74705SXin Li return getFinalReader().LookupUnqualified(R, S);
297*67e74705SXin Li }
298*67e74705SXin Li
299