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