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. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "IncrementalParser.h" 14 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/Parse/Parser.h" 22 #include "clang/Sema/Sema.h" 23 24 #include "llvm/Option/ArgList.h" 25 #include "llvm/Support/CrashRecoveryContext.h" 26 #include "llvm/Support/Error.h" 27 #include "llvm/Support/Timer.h" 28 29 #include <sstream> 30 31 namespace clang { 32 33 /// A custom action enabling the incremental processing functionality. 34 /// 35 /// The usual \p FrontendAction expects one call to ExecuteAction and once it 36 /// sees a call to \p EndSourceFile it deletes some of the important objects 37 /// such as \p Preprocessor and \p Sema assuming no further input will come. 38 /// 39 /// \p IncrementalAction ensures it keep its underlying action's objects alive 40 /// as long as the \p IncrementalParser needs them. 41 /// 42 class IncrementalAction : public WrapperFrontendAction { 43 private: 44 bool IsTerminating = false; 45 46 public: 47 IncrementalAction(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx, 48 llvm::Error &Err) 49 : WrapperFrontendAction([&]() { 50 llvm::ErrorAsOutParameter EAO(&Err); 51 std::unique_ptr<FrontendAction> Act; 52 switch (CI.getFrontendOpts().ProgramAction) { 53 default: 54 Err = llvm::createStringError( 55 std::errc::state_not_recoverable, 56 "Driver initialization failed. " 57 "Incremental mode for action is not supported"); 58 return Act; 59 case frontend::ASTDump: 60 LLVM_FALLTHROUGH; 61 case frontend::ASTPrint: 62 LLVM_FALLTHROUGH; 63 case frontend::ParseSyntaxOnly: 64 Act = CreateFrontendAction(CI); 65 break; 66 case frontend::EmitObj: 67 LLVM_FALLTHROUGH; 68 case frontend::EmitLLVMOnly: 69 Act.reset(new EmitLLVMOnlyAction(&LLVMCtx)); 70 break; 71 } 72 return Act; 73 }()) {} 74 FrontendAction *getWrapped() const { return WrappedAction.get(); } 75 void ExecuteAction() override { 76 CompilerInstance &CI = getCompilerInstance(); 77 assert(CI.hasPreprocessor() && "No PP!"); 78 79 // FIXME: Move the truncation aspect of this into Sema, we delayed this till 80 // here so the source manager would be initialized. 81 if (hasCodeCompletionSupport() && 82 !CI.getFrontendOpts().CodeCompletionAt.FileName.empty()) 83 CI.createCodeCompletionConsumer(); 84 85 // Use a code completion consumer? 86 CodeCompleteConsumer *CompletionConsumer = nullptr; 87 if (CI.hasCodeCompletionConsumer()) 88 CompletionConsumer = &CI.getCodeCompletionConsumer(); 89 90 Preprocessor &PP = CI.getPreprocessor(); 91 PP.enableIncrementalProcessing(); 92 PP.EnterMainSourceFile(); 93 94 if (!CI.hasSema()) 95 CI.createSema(getTranslationUnitKind(), CompletionConsumer); 96 } 97 98 // Do not terminate after processing the input. This allows us to keep various 99 // clang objects alive and to incrementally grow the current TU. 100 void EndSourceFile() override { 101 // The WrappedAction can be nullptr if we issued an error in the ctor. 102 if (IsTerminating && getWrapped()) 103 WrapperFrontendAction::EndSourceFile(); 104 } 105 106 void FinalizeAction() { 107 assert(!IsTerminating && "Already finalized!"); 108 IsTerminating = true; 109 EndSourceFile(); 110 } 111 }; 112 113 IncrementalParser::IncrementalParser(std::unique_ptr<CompilerInstance> Instance, 114 llvm::LLVMContext &LLVMCtx, 115 llvm::Error &Err) 116 : CI(std::move(Instance)) { 117 llvm::ErrorAsOutParameter EAO(&Err); 118 Act = std::make_unique<IncrementalAction>(*CI, LLVMCtx, Err); 119 if (Err) 120 return; 121 CI->ExecuteAction(*Act); 122 Consumer = &CI->getASTConsumer(); 123 P.reset( 124 new Parser(CI->getPreprocessor(), CI->getSema(), /*SkipBodies=*/false)); 125 P->Initialize(); 126 } 127 128 IncrementalParser::~IncrementalParser() { Act->FinalizeAction(); } 129 130 llvm::Expected<Transaction &> IncrementalParser::ParseOrWrapTopLevelDecl() { 131 DiagnosticsEngine &Diags = getCI()->getDiagnostics(); 132 133 if (Diags.hasErrorOccurred()) 134 llvm::report_fatal_error("Previous input had errors, " 135 "recovery not yet supported", 136 /*GenCrashDiag=*/false); 137 138 // Recover resources if we crash before exiting this method. 139 Sema &S = CI->getSema(); 140 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(&S); 141 Sema::GlobalEagerInstantiationScope GlobalInstantiations(S, /*Enabled=*/true); 142 Sema::LocalEagerInstantiationScope LocalInstantiations(S); 143 144 // Skip previous eof due to last incremental input. 145 if (P->getCurToken().is(tok::eof)) 146 P->ConsumeToken(); 147 148 Transactions.emplace_back(Transaction()); 149 Transaction &LastTransaction = Transactions.back(); 150 151 Parser::DeclGroupPtrTy ADecl; 152 for (bool AtEOF = P->ParseFirstTopLevelDecl(ADecl); !AtEOF; 153 AtEOF = P->ParseTopLevelDecl(ADecl)) { 154 // If we got a null return and something *was* parsed, ignore it. This 155 // is due to a top-level semicolon, an action override, or a parse error 156 // skipping something. 157 if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) 158 return llvm::make_error<llvm::StringError>("Parsing failed. " 159 "The consumer rejected a decl", 160 std::error_code()); 161 LastTransaction.Decls.push_back(ADecl.get()); 162 } 163 164 // Process any TopLevelDecls generated by #pragma weak. 165 for (Decl *D : S.WeakTopLevelDecls()) { 166 DeclGroupRef DGR(D); 167 LastTransaction.Decls.push_back(DGR); 168 Consumer->HandleTopLevelDecl(DGR); 169 } 170 171 LocalInstantiations.perform(); 172 GlobalInstantiations.perform(); 173 174 Consumer->HandleTranslationUnit(S.getASTContext()); 175 176 if (Diags.hasErrorOccurred()) 177 return llvm::make_error<llvm::StringError>("Parsing failed.", 178 std::error_code()); 179 180 return LastTransaction; 181 } 182 183 static CodeGenerator *getCodeGen(FrontendAction *Act) { 184 IncrementalAction *IncrAct = static_cast<IncrementalAction *>(Act); 185 FrontendAction *WrappedAct = IncrAct->getWrapped(); 186 if (!WrappedAct->hasIRSupport()) 187 return nullptr; 188 return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator(); 189 } 190 191 llvm::Expected<Transaction &> IncrementalParser::Parse(llvm::StringRef input) { 192 Preprocessor &PP = CI->getPreprocessor(); 193 assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode!?"); 194 195 std::ostringstream SourceName; 196 SourceName << "input_line_" << InputCount++; 197 198 // Create an uninitialized memory buffer, copy code in and append "\n" 199 size_t InputSize = input.size(); // don't include trailing 0 200 // MemBuffer size should *not* include terminating zero 201 std::unique_ptr<llvm::MemoryBuffer> MB( 202 llvm::WritableMemoryBuffer::getNewUninitMemBuffer(InputSize + 1, 203 SourceName.str())); 204 char *MBStart = const_cast<char *>(MB->getBufferStart()); 205 memcpy(MBStart, input.data(), InputSize); 206 MBStart[InputSize] = '\n'; 207 208 SourceManager &SM = CI->getSourceManager(); 209 210 // FIXME: Create SourceLocation, which will allow clang to order the overload 211 // candidates for example 212 SourceLocation NewLoc = SM.getLocForStartOfFile(SM.getMainFileID()); 213 214 // Create FileID for the current buffer. 215 FileID FID = SM.createFileID(std::move(MB), SrcMgr::C_User, /*LoadedID=*/0, 216 /*LoadedOffset=*/0, NewLoc); 217 218 // NewLoc only used for diags. 219 if (PP.EnterSourceFile(FID, /*DirLookup=*/0, NewLoc)) 220 return llvm::make_error<llvm::StringError>("Parsing failed. " 221 "Cannot enter source file.", 222 std::error_code()); 223 224 auto ErrOrTransaction = ParseOrWrapTopLevelDecl(); 225 if (auto Err = ErrOrTransaction.takeError()) 226 return std::move(Err); 227 228 if (PP.getLangOpts().DelayedTemplateParsing) { 229 // Microsoft-specific: 230 // Late parsed templates can leave unswallowed "macro"-like tokens. 231 // They will seriously confuse the Parser when entering the next 232 // source file. So lex until we are EOF. 233 Token Tok; 234 do { 235 PP.Lex(Tok); 236 } while (Tok.isNot(tok::eof)); 237 } 238 239 Token AssertTok; 240 PP.Lex(AssertTok); 241 assert(AssertTok.is(tok::eof) && 242 "Lexer must be EOF when starting incremental parse!"); 243 244 if (CodeGenerator *CG = getCodeGen(Act.get())) { 245 std::unique_ptr<llvm::Module> M(CG->ReleaseModule()); 246 CG->StartModule("incr_module_" + std::to_string(Transactions.size()), 247 M->getContext()); 248 249 ErrOrTransaction->TheModule = std::move(M); 250 } 251 252 return ErrOrTransaction; 253 } 254 } // end namespace clang 255