[lld][WebAssembly] Add `--table-base` setting
[llvm-project.git] / clang / lib / Interpreter / IncrementalParser.cpp
blob9e5cf358700b1b41000d7dd9fef8c61ccb9f2220
1 //===--------- IncrementalParser.cpp - Incremental Compilation -----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the class which performs incremental code compilation.
11 //===----------------------------------------------------------------------===//
13 #include "IncrementalParser.h"
14 #include "clang/AST/DeclContextInternals.h"
15 #include "clang/CodeGen/BackendUtil.h"
16 #include "clang/CodeGen/CodeGenAction.h"
17 #include "clang/CodeGen/ModuleBuilder.h"
18 #include "clang/Frontend/CompilerInstance.h"
19 #include "clang/Frontend/FrontendAction.h"
20 #include "clang/FrontendTool/Utils.h"
21 #include "clang/Interpreter/Interpreter.h"
22 #include "clang/Parse/Parser.h"
23 #include "clang/Sema/Sema.h"
24 #include "llvm/Option/ArgList.h"
25 #include "llvm/Support/CrashRecoveryContext.h"
26 #include "llvm/Support/Error.h"
27 #include "llvm/Support/Timer.h"
29 #include <sstream>
31 namespace clang {
33 class IncrementalASTConsumer final : public ASTConsumer {
34 Interpreter &Interp;
35 std::unique_ptr<ASTConsumer> Consumer;
37 public:
38 IncrementalASTConsumer(Interpreter &InterpRef, std::unique_ptr<ASTConsumer> C)
39 : Interp(InterpRef), Consumer(std::move(C)) {}
41 bool HandleTopLevelDecl(DeclGroupRef DGR) override final {
42 if (DGR.isNull())
43 return true;
44 if (!Consumer)
45 return true;
47 for (Decl *D : DGR)
48 if (auto *TSD = llvm::dyn_cast<TopLevelStmtDecl>(D);
49 TSD && TSD->isSemiMissing())
50 TSD->setStmt(Interp.SynthesizeExpr(cast<Expr>(TSD->getStmt())));
52 return Consumer->HandleTopLevelDecl(DGR);
54 void HandleTranslationUnit(ASTContext &Ctx) override final {
55 Consumer->HandleTranslationUnit(Ctx);
57 void HandleInlineFunctionDefinition(FunctionDecl *D) override final {
58 Consumer->HandleInlineFunctionDefinition(D);
60 void HandleInterestingDecl(DeclGroupRef D) override final {
61 Consumer->HandleInterestingDecl(D);
63 void HandleTagDeclDefinition(TagDecl *D) override final {
64 Consumer->HandleTagDeclDefinition(D);
66 void HandleTagDeclRequiredDefinition(const TagDecl *D) override final {
67 Consumer->HandleTagDeclRequiredDefinition(D);
69 void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override final {
70 Consumer->HandleCXXImplicitFunctionInstantiation(D);
72 void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override final {
73 Consumer->HandleTopLevelDeclInObjCContainer(D);
75 void HandleImplicitImportDecl(ImportDecl *D) override final {
76 Consumer->HandleImplicitImportDecl(D);
78 void CompleteTentativeDefinition(VarDecl *D) override final {
79 Consumer->CompleteTentativeDefinition(D);
81 void CompleteExternalDeclaration(VarDecl *D) override final {
82 Consumer->CompleteExternalDeclaration(D);
84 void AssignInheritanceModel(CXXRecordDecl *RD) override final {
85 Consumer->AssignInheritanceModel(RD);
87 void HandleCXXStaticMemberVarInstantiation(VarDecl *D) override final {
88 Consumer->HandleCXXStaticMemberVarInstantiation(D);
90 void HandleVTable(CXXRecordDecl *RD) override final {
91 Consumer->HandleVTable(RD);
93 ASTMutationListener *GetASTMutationListener() override final {
94 return Consumer->GetASTMutationListener();
96 ASTDeserializationListener *GetASTDeserializationListener() override final {
97 return Consumer->GetASTDeserializationListener();
99 void PrintStats() override final { Consumer->PrintStats(); }
100 bool shouldSkipFunctionBody(Decl *D) override final {
101 return Consumer->shouldSkipFunctionBody(D);
103 static bool classof(const clang::ASTConsumer *) { return true; }
106 /// A custom action enabling the incremental processing functionality.
108 /// The usual \p FrontendAction expects one call to ExecuteAction and once it
109 /// sees a call to \p EndSourceFile it deletes some of the important objects
110 /// such as \p Preprocessor and \p Sema assuming no further input will come.
112 /// \p IncrementalAction ensures it keep its underlying action's objects alive
113 /// as long as the \p IncrementalParser needs them.
115 class IncrementalAction : public WrapperFrontendAction {
116 private:
117 bool IsTerminating = false;
119 public:
120 IncrementalAction(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx,
121 llvm::Error &Err)
122 : WrapperFrontendAction([&]() {
123 llvm::ErrorAsOutParameter EAO(&Err);
124 std::unique_ptr<FrontendAction> Act;
125 switch (CI.getFrontendOpts().ProgramAction) {
126 default:
127 Err = llvm::createStringError(
128 std::errc::state_not_recoverable,
129 "Driver initialization failed. "
130 "Incremental mode for action %d is not supported",
131 CI.getFrontendOpts().ProgramAction);
132 return Act;
133 case frontend::ASTDump:
134 [[fallthrough]];
135 case frontend::ASTPrint:
136 [[fallthrough]];
137 case frontend::ParseSyntaxOnly:
138 Act = CreateFrontendAction(CI);
139 break;
140 case frontend::PluginAction:
141 [[fallthrough]];
142 case frontend::EmitAssembly:
143 [[fallthrough]];
144 case frontend::EmitBC:
145 [[fallthrough]];
146 case frontend::EmitObj:
147 [[fallthrough]];
148 case frontend::PrintPreprocessedInput:
149 [[fallthrough]];
150 case frontend::EmitLLVMOnly:
151 Act.reset(new EmitLLVMOnlyAction(&LLVMCtx));
152 break;
154 return Act;
155 }()) {}
156 FrontendAction *getWrapped() const { return WrappedAction.get(); }
157 TranslationUnitKind getTranslationUnitKind() override {
158 return TU_Incremental;
160 void ExecuteAction() override {
161 CompilerInstance &CI = getCompilerInstance();
162 assert(CI.hasPreprocessor() && "No PP!");
164 // FIXME: Move the truncation aspect of this into Sema, we delayed this till
165 // here so the source manager would be initialized.
166 if (hasCodeCompletionSupport() &&
167 !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
168 CI.createCodeCompletionConsumer();
170 // Use a code completion consumer?
171 CodeCompleteConsumer *CompletionConsumer = nullptr;
172 if (CI.hasCodeCompletionConsumer())
173 CompletionConsumer = &CI.getCodeCompletionConsumer();
175 Preprocessor &PP = CI.getPreprocessor();
176 PP.EnterMainSourceFile();
178 if (!CI.hasSema())
179 CI.createSema(getTranslationUnitKind(), CompletionConsumer);
182 // Do not terminate after processing the input. This allows us to keep various
183 // clang objects alive and to incrementally grow the current TU.
184 void EndSourceFile() override {
185 // The WrappedAction can be nullptr if we issued an error in the ctor.
186 if (IsTerminating && getWrapped())
187 WrapperFrontendAction::EndSourceFile();
190 void FinalizeAction() {
191 assert(!IsTerminating && "Already finalized!");
192 IsTerminating = true;
193 EndSourceFile();
197 CodeGenerator *IncrementalParser::getCodeGen() const {
198 FrontendAction *WrappedAct = Act->getWrapped();
199 if (!WrappedAct->hasIRSupport())
200 return nullptr;
201 return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator();
204 IncrementalParser::IncrementalParser() {}
206 IncrementalParser::IncrementalParser(Interpreter &Interp,
207 std::unique_ptr<CompilerInstance> Instance,
208 llvm::LLVMContext &LLVMCtx,
209 llvm::Error &Err)
210 : CI(std::move(Instance)) {
211 llvm::ErrorAsOutParameter EAO(&Err);
212 Act = std::make_unique<IncrementalAction>(*CI, LLVMCtx, Err);
213 if (Err)
214 return;
215 CI->ExecuteAction(*Act);
216 std::unique_ptr<ASTConsumer> IncrConsumer =
217 std::make_unique<IncrementalASTConsumer>(Interp, CI->takeASTConsumer());
218 CI->setASTConsumer(std::move(IncrConsumer));
219 Consumer = &CI->getASTConsumer();
220 P.reset(
221 new Parser(CI->getPreprocessor(), CI->getSema(), /*SkipBodies=*/false));
222 P->Initialize();
224 // An initial PTU is needed as CUDA includes some headers automatically
225 auto PTU = ParseOrWrapTopLevelDecl();
226 if (auto E = PTU.takeError()) {
227 consumeError(std::move(E)); // FIXME
228 return; // PTU.takeError();
231 if (CodeGenerator *CG = getCodeGen()) {
232 std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
233 CG->StartModule("incr_module_" + std::to_string(PTUs.size()),
234 M->getContext());
235 PTU->TheModule = std::move(M);
236 assert(PTU->TheModule && "Failed to create initial PTU");
240 IncrementalParser::~IncrementalParser() {
241 P.reset();
242 Act->FinalizeAction();
245 llvm::Expected<PartialTranslationUnit &>
246 IncrementalParser::ParseOrWrapTopLevelDecl() {
247 // Recover resources if we crash before exiting this method.
248 Sema &S = CI->getSema();
249 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(&S);
250 Sema::GlobalEagerInstantiationScope GlobalInstantiations(S, /*Enabled=*/true);
251 Sema::LocalEagerInstantiationScope LocalInstantiations(S);
253 PTUs.emplace_back(PartialTranslationUnit());
254 PartialTranslationUnit &LastPTU = PTUs.back();
255 // Add a new PTU.
256 ASTContext &C = S.getASTContext();
257 C.addTranslationUnitDecl();
258 LastPTU.TUPart = C.getTranslationUnitDecl();
260 // Skip previous eof due to last incremental input.
261 if (P->getCurToken().is(tok::annot_repl_input_end)) {
262 P->ConsumeAnyToken();
263 // FIXME: Clang does not call ExitScope on finalizing the regular TU, we
264 // might want to do that around HandleEndOfTranslationUnit.
265 P->ExitScope();
266 S.CurContext = nullptr;
267 // Start a new PTU.
268 P->EnterScope(Scope::DeclScope);
269 S.ActOnTranslationUnitScope(P->getCurScope());
272 Parser::DeclGroupPtrTy ADecl;
273 Sema::ModuleImportState ImportState;
274 for (bool AtEOF = P->ParseFirstTopLevelDecl(ADecl, ImportState); !AtEOF;
275 AtEOF = P->ParseTopLevelDecl(ADecl, ImportState)) {
276 if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
277 return llvm::make_error<llvm::StringError>("Parsing failed. "
278 "The consumer rejected a decl",
279 std::error_code());
282 DiagnosticsEngine &Diags = getCI()->getDiagnostics();
283 if (Diags.hasErrorOccurred()) {
284 PartialTranslationUnit MostRecentPTU = {C.getTranslationUnitDecl(),
285 nullptr};
286 CleanUpPTU(MostRecentPTU);
288 Diags.Reset(/*soft=*/true);
289 Diags.getClient()->clear();
290 return llvm::make_error<llvm::StringError>("Parsing failed.",
291 std::error_code());
294 // Process any TopLevelDecls generated by #pragma weak.
295 for (Decl *D : S.WeakTopLevelDecls()) {
296 DeclGroupRef DGR(D);
297 Consumer->HandleTopLevelDecl(DGR);
300 LocalInstantiations.perform();
301 GlobalInstantiations.perform();
303 Consumer->HandleTranslationUnit(C);
305 return LastPTU;
308 llvm::Expected<PartialTranslationUnit &>
309 IncrementalParser::Parse(llvm::StringRef input) {
310 Preprocessor &PP = CI->getPreprocessor();
311 assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode!?");
313 std::ostringstream SourceName;
314 SourceName << "input_line_" << InputCount++;
316 // Create an uninitialized memory buffer, copy code in and append "\n"
317 size_t InputSize = input.size(); // don't include trailing 0
318 // MemBuffer size should *not* include terminating zero
319 std::unique_ptr<llvm::MemoryBuffer> MB(
320 llvm::WritableMemoryBuffer::getNewUninitMemBuffer(InputSize + 1,
321 SourceName.str()));
322 char *MBStart = const_cast<char *>(MB->getBufferStart());
323 memcpy(MBStart, input.data(), InputSize);
324 MBStart[InputSize] = '\n';
326 SourceManager &SM = CI->getSourceManager();
328 // FIXME: Create SourceLocation, which will allow clang to order the overload
329 // candidates for example
330 SourceLocation NewLoc = SM.getLocForStartOfFile(SM.getMainFileID());
332 // Create FileID for the current buffer.
333 FileID FID = SM.createFileID(std::move(MB), SrcMgr::C_User, /*LoadedID=*/0,
334 /*LoadedOffset=*/0, NewLoc);
336 // NewLoc only used for diags.
337 if (PP.EnterSourceFile(FID, /*DirLookup=*/nullptr, NewLoc))
338 return llvm::make_error<llvm::StringError>("Parsing failed. "
339 "Cannot enter source file.",
340 std::error_code());
342 auto PTU = ParseOrWrapTopLevelDecl();
343 if (!PTU)
344 return PTU.takeError();
346 if (PP.getLangOpts().DelayedTemplateParsing) {
347 // Microsoft-specific:
348 // Late parsed templates can leave unswallowed "macro"-like tokens.
349 // They will seriously confuse the Parser when entering the next
350 // source file. So lex until we are EOF.
351 Token Tok;
352 do {
353 PP.Lex(Tok);
354 } while (Tok.isNot(tok::annot_repl_input_end));
355 } else {
356 Token AssertTok;
357 PP.Lex(AssertTok);
358 assert(AssertTok.is(tok::annot_repl_input_end) &&
359 "Lexer must be EOF when starting incremental parse!");
362 if (std::unique_ptr<llvm::Module> M = GenModule())
363 PTU->TheModule = std::move(M);
365 return PTU;
368 std::unique_ptr<llvm::Module> IncrementalParser::GenModule() {
369 static unsigned ID = 0;
370 if (CodeGenerator *CG = getCodeGen()) {
371 std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
372 CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext());
373 return M;
375 return nullptr;
378 void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) {
379 TranslationUnitDecl *MostRecentTU = PTU.TUPart;
380 TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl();
381 if (StoredDeclsMap *Map = FirstTU->getPrimaryContext()->getLookupPtr()) {
382 for (auto I = Map->begin(); I != Map->end(); ++I) {
383 StoredDeclsList &List = I->second;
384 DeclContextLookupResult R = List.getLookupResult();
385 for (NamedDecl *D : R) {
386 if (D->getTranslationUnitDecl() == MostRecentTU) {
387 List.remove(D);
390 if (List.isNull())
391 Map->erase(I);
396 llvm::StringRef IncrementalParser::GetMangledName(GlobalDecl GD) const {
397 CodeGenerator *CG = getCodeGen();
398 assert(CG);
399 return CG->GetMangledName(GD);
402 } // end namespace clang