1a9ac8606Spatrick //===--------- IncrementalParser.cpp - Incremental Compilation -----------===//
2a9ac8606Spatrick //
3a9ac8606Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a9ac8606Spatrick // See https://llvm.org/LICENSE.txt for license information.
5a9ac8606Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a9ac8606Spatrick //
7a9ac8606Spatrick //===----------------------------------------------------------------------===//
8a9ac8606Spatrick //
9a9ac8606Spatrick // This file implements the class which performs incremental code compilation.
10a9ac8606Spatrick //
11a9ac8606Spatrick //===----------------------------------------------------------------------===//
12a9ac8606Spatrick
13a9ac8606Spatrick #include "IncrementalParser.h"
14a9ac8606Spatrick
15a9ac8606Spatrick #include "clang/AST/DeclContextInternals.h"
16a9ac8606Spatrick #include "clang/CodeGen/BackendUtil.h"
17a9ac8606Spatrick #include "clang/CodeGen/CodeGenAction.h"
18a9ac8606Spatrick #include "clang/CodeGen/ModuleBuilder.h"
19a9ac8606Spatrick #include "clang/Frontend/CompilerInstance.h"
20a9ac8606Spatrick #include "clang/Frontend/FrontendAction.h"
21a9ac8606Spatrick #include "clang/FrontendTool/Utils.h"
22a9ac8606Spatrick #include "clang/Parse/Parser.h"
23a9ac8606Spatrick #include "clang/Sema/Sema.h"
24a9ac8606Spatrick
25a9ac8606Spatrick #include "llvm/Option/ArgList.h"
26a9ac8606Spatrick #include "llvm/Support/CrashRecoveryContext.h"
27a9ac8606Spatrick #include "llvm/Support/Error.h"
28a9ac8606Spatrick #include "llvm/Support/Timer.h"
29a9ac8606Spatrick
30a9ac8606Spatrick #include <sstream>
31a9ac8606Spatrick
32a9ac8606Spatrick namespace clang {
33a9ac8606Spatrick
34a9ac8606Spatrick /// A custom action enabling the incremental processing functionality.
35a9ac8606Spatrick ///
36a9ac8606Spatrick /// The usual \p FrontendAction expects one call to ExecuteAction and once it
37a9ac8606Spatrick /// sees a call to \p EndSourceFile it deletes some of the important objects
38a9ac8606Spatrick /// such as \p Preprocessor and \p Sema assuming no further input will come.
39a9ac8606Spatrick ///
40a9ac8606Spatrick /// \p IncrementalAction ensures it keep its underlying action's objects alive
41a9ac8606Spatrick /// as long as the \p IncrementalParser needs them.
42a9ac8606Spatrick ///
43a9ac8606Spatrick class IncrementalAction : public WrapperFrontendAction {
44a9ac8606Spatrick private:
45a9ac8606Spatrick bool IsTerminating = false;
46a9ac8606Spatrick
47a9ac8606Spatrick public:
IncrementalAction(CompilerInstance & CI,llvm::LLVMContext & LLVMCtx,llvm::Error & Err)48a9ac8606Spatrick IncrementalAction(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx,
49a9ac8606Spatrick llvm::Error &Err)
50a9ac8606Spatrick : WrapperFrontendAction([&]() {
51a9ac8606Spatrick llvm::ErrorAsOutParameter EAO(&Err);
52a9ac8606Spatrick std::unique_ptr<FrontendAction> Act;
53a9ac8606Spatrick switch (CI.getFrontendOpts().ProgramAction) {
54a9ac8606Spatrick default:
55a9ac8606Spatrick Err = llvm::createStringError(
56a9ac8606Spatrick std::errc::state_not_recoverable,
57a9ac8606Spatrick "Driver initialization failed. "
58a9ac8606Spatrick "Incremental mode for action %d is not supported",
59a9ac8606Spatrick CI.getFrontendOpts().ProgramAction);
60a9ac8606Spatrick return Act;
61a9ac8606Spatrick case frontend::ASTDump:
62*12c85518Srobert [[fallthrough]];
63a9ac8606Spatrick case frontend::ASTPrint:
64*12c85518Srobert [[fallthrough]];
65a9ac8606Spatrick case frontend::ParseSyntaxOnly:
66a9ac8606Spatrick Act = CreateFrontendAction(CI);
67a9ac8606Spatrick break;
68*12c85518Srobert case frontend::PluginAction:
69*12c85518Srobert [[fallthrough]];
70a9ac8606Spatrick case frontend::EmitAssembly:
71*12c85518Srobert [[fallthrough]];
72*12c85518Srobert case frontend::EmitBC:
73*12c85518Srobert [[fallthrough]];
74a9ac8606Spatrick case frontend::EmitObj:
75*12c85518Srobert [[fallthrough]];
76*12c85518Srobert case frontend::PrintPreprocessedInput:
77*12c85518Srobert [[fallthrough]];
78a9ac8606Spatrick case frontend::EmitLLVMOnly:
79a9ac8606Spatrick Act.reset(new EmitLLVMOnlyAction(&LLVMCtx));
80a9ac8606Spatrick break;
81a9ac8606Spatrick }
82a9ac8606Spatrick return Act;
83a9ac8606Spatrick }()) {}
getWrapped() const84a9ac8606Spatrick FrontendAction *getWrapped() const { return WrappedAction.get(); }
getTranslationUnitKind()85a9ac8606Spatrick TranslationUnitKind getTranslationUnitKind() override {
86a9ac8606Spatrick return TU_Incremental;
87a9ac8606Spatrick }
ExecuteAction()88a9ac8606Spatrick void ExecuteAction() override {
89a9ac8606Spatrick CompilerInstance &CI = getCompilerInstance();
90a9ac8606Spatrick assert(CI.hasPreprocessor() && "No PP!");
91a9ac8606Spatrick
92a9ac8606Spatrick // FIXME: Move the truncation aspect of this into Sema, we delayed this till
93a9ac8606Spatrick // here so the source manager would be initialized.
94a9ac8606Spatrick if (hasCodeCompletionSupport() &&
95a9ac8606Spatrick !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
96a9ac8606Spatrick CI.createCodeCompletionConsumer();
97a9ac8606Spatrick
98a9ac8606Spatrick // Use a code completion consumer?
99a9ac8606Spatrick CodeCompleteConsumer *CompletionConsumer = nullptr;
100a9ac8606Spatrick if (CI.hasCodeCompletionConsumer())
101a9ac8606Spatrick CompletionConsumer = &CI.getCodeCompletionConsumer();
102a9ac8606Spatrick
103a9ac8606Spatrick Preprocessor &PP = CI.getPreprocessor();
104a9ac8606Spatrick PP.EnterMainSourceFile();
105a9ac8606Spatrick
106a9ac8606Spatrick if (!CI.hasSema())
107a9ac8606Spatrick CI.createSema(getTranslationUnitKind(), CompletionConsumer);
108a9ac8606Spatrick }
109a9ac8606Spatrick
110a9ac8606Spatrick // Do not terminate after processing the input. This allows us to keep various
111a9ac8606Spatrick // clang objects alive and to incrementally grow the current TU.
EndSourceFile()112a9ac8606Spatrick void EndSourceFile() override {
113a9ac8606Spatrick // The WrappedAction can be nullptr if we issued an error in the ctor.
114a9ac8606Spatrick if (IsTerminating && getWrapped())
115a9ac8606Spatrick WrapperFrontendAction::EndSourceFile();
116a9ac8606Spatrick }
117a9ac8606Spatrick
FinalizeAction()118a9ac8606Spatrick void FinalizeAction() {
119a9ac8606Spatrick assert(!IsTerminating && "Already finalized!");
120a9ac8606Spatrick IsTerminating = true;
121a9ac8606Spatrick EndSourceFile();
122a9ac8606Spatrick }
123a9ac8606Spatrick };
124a9ac8606Spatrick
IncrementalParser(std::unique_ptr<CompilerInstance> Instance,llvm::LLVMContext & LLVMCtx,llvm::Error & Err)125a9ac8606Spatrick IncrementalParser::IncrementalParser(std::unique_ptr<CompilerInstance> Instance,
126a9ac8606Spatrick llvm::LLVMContext &LLVMCtx,
127a9ac8606Spatrick llvm::Error &Err)
128a9ac8606Spatrick : CI(std::move(Instance)) {
129a9ac8606Spatrick llvm::ErrorAsOutParameter EAO(&Err);
130a9ac8606Spatrick Act = std::make_unique<IncrementalAction>(*CI, LLVMCtx, Err);
131a9ac8606Spatrick if (Err)
132a9ac8606Spatrick return;
133a9ac8606Spatrick CI->ExecuteAction(*Act);
134a9ac8606Spatrick Consumer = &CI->getASTConsumer();
135a9ac8606Spatrick P.reset(
136a9ac8606Spatrick new Parser(CI->getPreprocessor(), CI->getSema(), /*SkipBodies=*/false));
137a9ac8606Spatrick P->Initialize();
138a9ac8606Spatrick }
139a9ac8606Spatrick
~IncrementalParser()140*12c85518Srobert IncrementalParser::~IncrementalParser() {
141*12c85518Srobert P.reset();
142*12c85518Srobert Act->FinalizeAction();
143*12c85518Srobert }
144a9ac8606Spatrick
145a9ac8606Spatrick llvm::Expected<PartialTranslationUnit &>
ParseOrWrapTopLevelDecl()146a9ac8606Spatrick IncrementalParser::ParseOrWrapTopLevelDecl() {
147a9ac8606Spatrick // Recover resources if we crash before exiting this method.
148a9ac8606Spatrick Sema &S = CI->getSema();
149a9ac8606Spatrick llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(&S);
150a9ac8606Spatrick Sema::GlobalEagerInstantiationScope GlobalInstantiations(S, /*Enabled=*/true);
151a9ac8606Spatrick Sema::LocalEagerInstantiationScope LocalInstantiations(S);
152a9ac8606Spatrick
153a9ac8606Spatrick PTUs.emplace_back(PartialTranslationUnit());
154a9ac8606Spatrick PartialTranslationUnit &LastPTU = PTUs.back();
155a9ac8606Spatrick // Add a new PTU.
156a9ac8606Spatrick ASTContext &C = S.getASTContext();
157a9ac8606Spatrick C.addTranslationUnitDecl();
158a9ac8606Spatrick LastPTU.TUPart = C.getTranslationUnitDecl();
159a9ac8606Spatrick
160a9ac8606Spatrick // Skip previous eof due to last incremental input.
161a9ac8606Spatrick if (P->getCurToken().is(tok::eof)) {
162a9ac8606Spatrick P->ConsumeToken();
163a9ac8606Spatrick // FIXME: Clang does not call ExitScope on finalizing the regular TU, we
164a9ac8606Spatrick // might want to do that around HandleEndOfTranslationUnit.
165a9ac8606Spatrick P->ExitScope();
166a9ac8606Spatrick S.CurContext = nullptr;
167a9ac8606Spatrick // Start a new PTU.
168a9ac8606Spatrick P->EnterScope(Scope::DeclScope);
169a9ac8606Spatrick S.ActOnTranslationUnitScope(P->getCurScope());
170a9ac8606Spatrick }
171a9ac8606Spatrick
172a9ac8606Spatrick Parser::DeclGroupPtrTy ADecl;
173*12c85518Srobert Sema::ModuleImportState ImportState;
174*12c85518Srobert for (bool AtEOF = P->ParseFirstTopLevelDecl(ADecl, ImportState); !AtEOF;
175*12c85518Srobert AtEOF = P->ParseTopLevelDecl(ADecl, ImportState)) {
176a9ac8606Spatrick if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
177a9ac8606Spatrick return llvm::make_error<llvm::StringError>("Parsing failed. "
178a9ac8606Spatrick "The consumer rejected a decl",
179a9ac8606Spatrick std::error_code());
180a9ac8606Spatrick }
181a9ac8606Spatrick
182a9ac8606Spatrick DiagnosticsEngine &Diags = getCI()->getDiagnostics();
183a9ac8606Spatrick if (Diags.hasErrorOccurred()) {
184*12c85518Srobert PartialTranslationUnit MostRecentPTU = {C.getTranslationUnitDecl(),
185*12c85518Srobert nullptr};
186*12c85518Srobert CleanUpPTU(MostRecentPTU);
187a9ac8606Spatrick
188*12c85518Srobert Diags.Reset(/*soft=*/true);
189*12c85518Srobert Diags.getClient()->clear();
190a9ac8606Spatrick return llvm::make_error<llvm::StringError>("Parsing failed.",
191a9ac8606Spatrick std::error_code());
192a9ac8606Spatrick }
193a9ac8606Spatrick
194a9ac8606Spatrick // Process any TopLevelDecls generated by #pragma weak.
195a9ac8606Spatrick for (Decl *D : S.WeakTopLevelDecls()) {
196a9ac8606Spatrick DeclGroupRef DGR(D);
197a9ac8606Spatrick Consumer->HandleTopLevelDecl(DGR);
198a9ac8606Spatrick }
199a9ac8606Spatrick
200a9ac8606Spatrick LocalInstantiations.perform();
201a9ac8606Spatrick GlobalInstantiations.perform();
202a9ac8606Spatrick
203a9ac8606Spatrick Consumer->HandleTranslationUnit(C);
204a9ac8606Spatrick
205a9ac8606Spatrick return LastPTU;
206a9ac8606Spatrick }
207a9ac8606Spatrick
getCodeGen(FrontendAction * Act)208a9ac8606Spatrick static CodeGenerator *getCodeGen(FrontendAction *Act) {
209a9ac8606Spatrick IncrementalAction *IncrAct = static_cast<IncrementalAction *>(Act);
210a9ac8606Spatrick FrontendAction *WrappedAct = IncrAct->getWrapped();
211a9ac8606Spatrick if (!WrappedAct->hasIRSupport())
212a9ac8606Spatrick return nullptr;
213a9ac8606Spatrick return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator();
214a9ac8606Spatrick }
215a9ac8606Spatrick
216a9ac8606Spatrick llvm::Expected<PartialTranslationUnit &>
Parse(llvm::StringRef input)217a9ac8606Spatrick IncrementalParser::Parse(llvm::StringRef input) {
218a9ac8606Spatrick Preprocessor &PP = CI->getPreprocessor();
219a9ac8606Spatrick assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode!?");
220a9ac8606Spatrick
221a9ac8606Spatrick std::ostringstream SourceName;
222a9ac8606Spatrick SourceName << "input_line_" << InputCount++;
223a9ac8606Spatrick
224a9ac8606Spatrick // Create an uninitialized memory buffer, copy code in and append "\n"
225a9ac8606Spatrick size_t InputSize = input.size(); // don't include trailing 0
226a9ac8606Spatrick // MemBuffer size should *not* include terminating zero
227a9ac8606Spatrick std::unique_ptr<llvm::MemoryBuffer> MB(
228a9ac8606Spatrick llvm::WritableMemoryBuffer::getNewUninitMemBuffer(InputSize + 1,
229a9ac8606Spatrick SourceName.str()));
230a9ac8606Spatrick char *MBStart = const_cast<char *>(MB->getBufferStart());
231a9ac8606Spatrick memcpy(MBStart, input.data(), InputSize);
232a9ac8606Spatrick MBStart[InputSize] = '\n';
233a9ac8606Spatrick
234a9ac8606Spatrick SourceManager &SM = CI->getSourceManager();
235a9ac8606Spatrick
236a9ac8606Spatrick // FIXME: Create SourceLocation, which will allow clang to order the overload
237a9ac8606Spatrick // candidates for example
238a9ac8606Spatrick SourceLocation NewLoc = SM.getLocForStartOfFile(SM.getMainFileID());
239a9ac8606Spatrick
240a9ac8606Spatrick // Create FileID for the current buffer.
241a9ac8606Spatrick FileID FID = SM.createFileID(std::move(MB), SrcMgr::C_User, /*LoadedID=*/0,
242a9ac8606Spatrick /*LoadedOffset=*/0, NewLoc);
243a9ac8606Spatrick
244a9ac8606Spatrick // NewLoc only used for diags.
245*12c85518Srobert if (PP.EnterSourceFile(FID, /*DirLookup=*/nullptr, NewLoc))
246a9ac8606Spatrick return llvm::make_error<llvm::StringError>("Parsing failed. "
247a9ac8606Spatrick "Cannot enter source file.",
248a9ac8606Spatrick std::error_code());
249a9ac8606Spatrick
250a9ac8606Spatrick auto PTU = ParseOrWrapTopLevelDecl();
251a9ac8606Spatrick if (!PTU)
252a9ac8606Spatrick return PTU.takeError();
253a9ac8606Spatrick
254a9ac8606Spatrick if (PP.getLangOpts().DelayedTemplateParsing) {
255a9ac8606Spatrick // Microsoft-specific:
256a9ac8606Spatrick // Late parsed templates can leave unswallowed "macro"-like tokens.
257a9ac8606Spatrick // They will seriously confuse the Parser when entering the next
258a9ac8606Spatrick // source file. So lex until we are EOF.
259a9ac8606Spatrick Token Tok;
260a9ac8606Spatrick do {
261a9ac8606Spatrick PP.Lex(Tok);
262a9ac8606Spatrick } while (Tok.isNot(tok::eof));
263a9ac8606Spatrick }
264a9ac8606Spatrick
265a9ac8606Spatrick Token AssertTok;
266a9ac8606Spatrick PP.Lex(AssertTok);
267a9ac8606Spatrick assert(AssertTok.is(tok::eof) &&
268a9ac8606Spatrick "Lexer must be EOF when starting incremental parse!");
269a9ac8606Spatrick
270a9ac8606Spatrick if (CodeGenerator *CG = getCodeGen(Act.get())) {
271a9ac8606Spatrick std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
272a9ac8606Spatrick CG->StartModule("incr_module_" + std::to_string(PTUs.size()),
273a9ac8606Spatrick M->getContext());
274a9ac8606Spatrick
275a9ac8606Spatrick PTU->TheModule = std::move(M);
276a9ac8606Spatrick }
277a9ac8606Spatrick
278a9ac8606Spatrick return PTU;
279a9ac8606Spatrick }
280*12c85518Srobert
CleanUpPTU(PartialTranslationUnit & PTU)281*12c85518Srobert void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) {
282*12c85518Srobert TranslationUnitDecl *MostRecentTU = PTU.TUPart;
283*12c85518Srobert TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl();
284*12c85518Srobert if (StoredDeclsMap *Map = FirstTU->getPrimaryContext()->getLookupPtr()) {
285*12c85518Srobert for (auto I = Map->begin(); I != Map->end(); ++I) {
286*12c85518Srobert StoredDeclsList &List = I->second;
287*12c85518Srobert DeclContextLookupResult R = List.getLookupResult();
288*12c85518Srobert for (NamedDecl *D : R) {
289*12c85518Srobert if (D->getTranslationUnitDecl() == MostRecentTU) {
290*12c85518Srobert List.remove(D);
291*12c85518Srobert }
292*12c85518Srobert }
293*12c85518Srobert if (List.isNull())
294*12c85518Srobert Map->erase(I);
295*12c85518Srobert }
296*12c85518Srobert }
297*12c85518Srobert }
298*12c85518Srobert
GetMangledName(GlobalDecl GD) const299*12c85518Srobert llvm::StringRef IncrementalParser::GetMangledName(GlobalDecl GD) const {
300*12c85518Srobert CodeGenerator *CG = getCodeGen(Act.get());
301*12c85518Srobert assert(CG);
302*12c85518Srobert return CG->GetMangledName(GD);
303*12c85518Srobert }
304*12c85518Srobert
305a9ac8606Spatrick } // end namespace clang
306