diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 83d2962cbf3ba..8c124aadf1005 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -37,7 +37,6 @@ class ThreadSafeContext; namespace clang { class CompilerInstance; -class CodeGenerator; class CXXRecordDecl; class Decl; class IncrementalExecutor; @@ -110,10 +109,6 @@ class Interpreter { // printing happens, it's in an invalid state. Value LastValue; - /// When CodeGen is created the first llvm::Module gets cached in many places - /// and we must keep it alive. - std::unique_ptr CachedInCodeGenModule; - /// Compiler instance performing the incremental compilation. std::unique_ptr CI; @@ -175,15 +170,9 @@ class Interpreter { llvm::Expected getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const; - std::unique_ptr GenModule(IncrementalAction *Action = nullptr); - PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU, - std::unique_ptr M = {}, - IncrementalAction *Action = nullptr); - private: size_t getEffectivePTUSize() const; void markUserCodeStart(); - llvm::Expected ExtractValueFromExpr(Expr *E); // A cache for the compiled destructors used to for de-allocation of managed // clang::Values. @@ -206,11 +195,6 @@ class Interpreter { // This function forces emission of the needed dtor. llvm::Expected CompileDtorCall(CXXRecordDecl *CXXRD) const; - - /// @} - /// @name Code generation - /// @{ - CodeGenerator *getCodeGen(IncrementalAction *Action = nullptr) const; }; } // namespace clang diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt index 70de4a2aaa541..d8dda45644668 100644 --- a/clang/lib/Interpreter/CMakeLists.txt +++ b/clang/lib/Interpreter/CMakeLists.txt @@ -22,6 +22,7 @@ endif() add_clang_library(clangInterpreter DeviceOffload.cpp CodeCompletion.cpp + IncrementalAction.cpp IncrementalExecutor.cpp IncrementalParser.cpp Interpreter.cpp diff --git a/clang/lib/Interpreter/DeviceOffload.cpp b/clang/lib/Interpreter/DeviceOffload.cpp index 9a25a264b2d5c..7c3404e02e328 100644 --- a/clang/lib/Interpreter/DeviceOffload.cpp +++ b/clang/lib/Interpreter/DeviceOffload.cpp @@ -26,9 +26,10 @@ namespace clang { IncrementalCUDADeviceParser::IncrementalCUDADeviceParser( CompilerInstance &DeviceInstance, CompilerInstance &HostInstance, + IncrementalAction *DeviceAct, llvm::IntrusiveRefCntPtr FS, - llvm::Error &Err, const std::list &PTUs) - : IncrementalParser(DeviceInstance, Err), PTUs(PTUs), VFS(FS), + llvm::Error &Err, std::list &PTUs) + : IncrementalParser(DeviceInstance, DeviceAct, Err, PTUs), VFS(FS), CodeGenOpts(HostInstance.getCodeGenOpts()), TargetOpts(DeviceInstance.getTargetOpts()) { if (Err) diff --git a/clang/lib/Interpreter/DeviceOffload.h b/clang/lib/Interpreter/DeviceOffload.h index 0b903e31c6799..a31bd5a0499b8 100644 --- a/clang/lib/Interpreter/DeviceOffload.h +++ b/clang/lib/Interpreter/DeviceOffload.h @@ -22,15 +22,16 @@ struct PartialTranslationUnit; class CompilerInstance; class CodeGenOptions; class TargetOptions; +class IncrementalAction; class IncrementalCUDADeviceParser : public IncrementalParser { - const std::list &PTUs; public: IncrementalCUDADeviceParser( CompilerInstance &DeviceInstance, CompilerInstance &HostInstance, + IncrementalAction *DeviceAct, llvm::IntrusiveRefCntPtr VFS, - llvm::Error &Err, const std::list &PTUs); + llvm::Error &Err, std::list &PTUs); // Generate PTX for the last PTU. llvm::Expected GeneratePTX(); diff --git a/clang/lib/Interpreter/IncrementalAction.cpp b/clang/lib/Interpreter/IncrementalAction.cpp new file mode 100644 index 0000000000000..67313a8cd2a8c --- /dev/null +++ b/clang/lib/Interpreter/IncrementalAction.cpp @@ -0,0 +1,151 @@ +//===--- IncrementalAction.h - Incremental Frontend Action -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "IncrementalAction.h" + +#include "clang/AST/ASTConsumer.h" +#include "clang/CodeGen/CodeGenAction.h" +#include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendOptions.h" +#include "clang/FrontendTool/Utils.h" +#include "clang/Interpreter/Interpreter.h" +#include "clang/Lex/PreprocessorOptions.h" +#include "clang/Sema/Sema.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" + +namespace clang { +IncrementalAction::IncrementalAction(CompilerInstance &CI, + llvm::LLVMContext &LLVMCtx, + llvm::Error &Err, Interpreter &I, + std::unique_ptr Consumer) + : WrapperFrontendAction([&]() { + llvm::ErrorAsOutParameter EAO(&Err); + std::unique_ptr Act; + switch (CI.getFrontendOpts().ProgramAction) { + default: + Err = llvm::createStringError( + std::errc::state_not_recoverable, + "Driver initialization failed. " + "Incremental mode for action %d is not supported", + CI.getFrontendOpts().ProgramAction); + return Act; + case frontend::ASTDump: + case frontend::ASTPrint: + case frontend::ParseSyntaxOnly: + Act = CreateFrontendAction(CI); + break; + case frontend::PluginAction: + case frontend::EmitAssembly: + case frontend::EmitBC: + case frontend::EmitObj: + case frontend::PrintPreprocessedInput: + case frontend::EmitLLVMOnly: + Act.reset(new EmitLLVMOnlyAction(&LLVMCtx)); + break; + } + return Act; + }()), + Interp(I), CI(CI), Consumer(std::move(Consumer)) {} + +std::unique_ptr +IncrementalAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { + std::unique_ptr C = + WrapperFrontendAction::CreateASTConsumer(CI, InFile); + + if (Consumer) { + std::vector> Cs; + Cs.push_back(std::move(Consumer)); + Cs.push_back(std::move(C)); + return std::make_unique(std::move(Cs)); + } + + return std::make_unique(std::move(C), Interp); +} + +void IncrementalAction::ExecuteAction() { + WrapperFrontendAction::ExecuteAction(); + getCompilerInstance().getSema().CurContext = nullptr; +} + +void IncrementalAction::EndSourceFile() { + if (IsTerminating && getWrapped()) + WrapperFrontendAction::EndSourceFile(); +} + +void IncrementalAction::FinalizeAction() { + assert(!IsTerminating && "Already finalized!"); + IsTerminating = true; + EndSourceFile(); +} + +void IncrementalAction::CacheCodeGenModule() { + CachedInCodeGenModule = GenModule(); +} + +llvm::Module *IncrementalAction::getCachedCodeGenModule() const { + return CachedInCodeGenModule.get(); +} + +std::unique_ptr IncrementalAction::GenModule() { + static unsigned ID = 0; + if (CodeGenerator *CG = getCodeGen()) { + // Clang's CodeGen is designed to work with a single llvm::Module. In many + // cases for convenience various CodeGen parts have a reference to the + // llvm::Module (TheModule or Module) which does not change when a new + // module is pushed. However, the execution engine wants to take ownership + // of the module which does not map well to CodeGen's design. To work this + // around we created an empty module to make CodeGen happy. We should make + // sure it always stays empty. + assert(((!CachedInCodeGenModule || + !CI.getPreprocessorOpts().Includes.empty()) || + (CachedInCodeGenModule->empty() && + CachedInCodeGenModule->global_empty() && + CachedInCodeGenModule->alias_empty() && + CachedInCodeGenModule->ifunc_empty())) && + "CodeGen wrote to a readonly module"); + std::unique_ptr M(CG->ReleaseModule()); + CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext()); + return M; + } + return nullptr; +} + +CodeGenerator *IncrementalAction::getCodeGen() const { + FrontendAction *WrappedAct = getWrapped(); + if (!WrappedAct || !WrappedAct->hasIRSupport()) + return nullptr; + return static_cast(WrappedAct)->getCodeGenerator(); +} + +InProcessPrintingASTConsumer::InProcessPrintingASTConsumer( + std::unique_ptr C, Interpreter &I) + : MultiplexConsumer(std::move(C)), Interp(I) {} + +bool InProcessPrintingASTConsumer::HandleTopLevelDecl(DeclGroupRef DGR) { + if (DGR.isNull()) + return true; + + for (Decl *D : DGR) + if (auto *TLSD = llvm::dyn_cast(D)) + if (TLSD && TLSD->isSemiMissing()) { + auto ExprOrErr = Interp.convertExprToValue(cast(TLSD->getStmt())); + if (llvm::Error E = ExprOrErr.takeError()) { + llvm::logAllUnhandledErrors(std::move(E), llvm::errs(), + "Value printing failed: "); + return false; // abort parsing + } + TLSD->setStmt(*ExprOrErr); + } + + return MultiplexConsumer::HandleTopLevelDecl(DGR); +} + +} // namespace clang \ No newline at end of file diff --git a/clang/lib/Interpreter/IncrementalAction.h b/clang/lib/Interpreter/IncrementalAction.h new file mode 100644 index 0000000000000..92eabacd40074 --- /dev/null +++ b/clang/lib/Interpreter/IncrementalAction.h @@ -0,0 +1,90 @@ +//===--- IncrementalAction.h - Incremental Frontend Action -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INTERPRETER_INCREMENTALACTION_H +#define LLVM_CLANG_INTERPRETER_INCREMENTALACTION_H + +#include "clang/Frontend/FrontendActions.h" +#include "clang/Frontend/MultiplexConsumer.h" + +namespace llvm { +class Module; +} + +namespace clang { + +class Interpreter; +class CodeGenerator; + +/// A custom action enabling the incremental processing functionality. +/// +/// The usual \p FrontendAction expects one call to ExecuteAction and once it +/// sees a call to \p EndSourceFile it deletes some of the important objects +/// such as \p Preprocessor and \p Sema assuming no further input will come. +/// +/// \p IncrementalAction ensures it keep its underlying action's objects alive +/// as long as the \p IncrementalParser needs them. +/// +class IncrementalAction : public WrapperFrontendAction { +private: + bool IsTerminating = false; + Interpreter &Interp; + CompilerInstance &CI; + std::unique_ptr Consumer; + + /// When CodeGen is created the first llvm::Module gets cached in many places + /// and we must keep it alive. + std::unique_ptr CachedInCodeGenModule; + +public: + IncrementalAction(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx, + llvm::Error &Err, Interpreter &I, + std::unique_ptr Consumer = nullptr); + + FrontendAction *getWrapped() const { return WrappedAction.get(); } + + TranslationUnitKind getTranslationUnitKind() override { + return TU_Incremental; + } + + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + + void ExecuteAction() override; + + // Do not terminate after processing the input. This allows us to keep various + // clang objects alive and to incrementally grow the current TU. + void EndSourceFile() override; + + void FinalizeAction(); + + /// Cache the current CodeGen module to preserve internal references. + void CacheCodeGenModule(); + + /// Access the cached CodeGen module. + llvm::Module *getCachedCodeGenModule() const; + + /// Access the current code generator. + CodeGenerator *getCodeGen() const; + + /// Generate an LLVM module for the most recent parsed input. + std::unique_ptr GenModule(); +}; + +class InProcessPrintingASTConsumer final : public MultiplexConsumer { + Interpreter &Interp; + +public: + InProcessPrintingASTConsumer(std::unique_ptr C, Interpreter &I); + + bool HandleTopLevelDecl(DeclGroupRef DGR) override; +}; + +} // end namespace clang + +#endif // LLVM_CLANG_INTERPRETER_INCREMENTALACTION_H diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index 6343f17ed822a..32d1663fbe1a9 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -11,24 +11,29 @@ //===----------------------------------------------------------------------===// #include "IncrementalParser.h" +#include "IncrementalAction.h" #include "clang/AST/DeclContextInternals.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Interpreter/PartialTranslationUnit.h" #include "clang/Parse/Parser.h" #include "clang/Sema/Sema.h" +#include "llvm/IR/Module.h" #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/Error.h" #include +#define DEBUG_TYPE "clang-repl" + namespace clang { // IncrementalParser::IncrementalParser() {} IncrementalParser::IncrementalParser(CompilerInstance &Instance, - llvm::Error &Err) - : S(Instance.getSema()) { + IncrementalAction *Act, llvm::Error &Err, + std::list &PTUs) + : S(Instance.getSema()), Act(Act), PTUs(PTUs) { llvm::ErrorAsOutParameter EAO(&Err); Consumer = &S.getASTConsumer(); P.reset(new Parser(S.getPreprocessor(), S, /*SkipBodies=*/false)); @@ -185,4 +190,25 @@ void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) { } } +PartialTranslationUnit & +IncrementalParser::RegisterPTU(TranslationUnitDecl *TU, + std::unique_ptr M /*={}*/) { + PTUs.emplace_back(PartialTranslationUnit()); + PartialTranslationUnit &LastPTU = PTUs.back(); + LastPTU.TUPart = TU; + + if (!M) + M = Act->GenModule(); + + assert((!Act->getCodeGen() || M) && "Must have a llvm::Module at this point"); + + LastPTU.TheModule = std::move(M); + LLVM_DEBUG(llvm::dbgs() << "compile-ptu " << PTUs.size() - 1 + << ": [TU=" << LastPTU.TUPart); + if (LastPTU.TheModule) + LLVM_DEBUG(llvm::dbgs() << ", M=" << LastPTU.TheModule.get() << " (" + << LastPTU.TheModule->getName() << ")"); + LLVM_DEBUG(llvm::dbgs() << "]\n"); + return LastPTU; +} } // end namespace clang diff --git a/clang/lib/Interpreter/IncrementalParser.h b/clang/lib/Interpreter/IncrementalParser.h index 4fdde749a2e75..9b042bc494efb 100644 --- a/clang/lib/Interpreter/IncrementalParser.h +++ b/clang/lib/Interpreter/IncrementalParser.h @@ -19,13 +19,18 @@ #include #include +namespace llvm { +class Module; +} + namespace clang { class ASTConsumer; -class CodeGenerator; class CompilerInstance; class Parser; class Sema; class TranslationUnitDecl; +class IncrementalAction; +struct PartialTranslationUnit; /// Provides support for incremental compilation. Keeps track of the state /// changes between the subsequent incremental input. @@ -44,10 +49,14 @@ class IncrementalParser { /// Counts the number of direct user input lines that have been parsed. unsigned InputCount = 0; - // IncrementalParser(); + /// The FrontendAction used during incremental parsing. + IncrementalAction *Act = nullptr; + + std::list &PTUs; public: - IncrementalParser(CompilerInstance &Instance, llvm::Error &Err); + IncrementalParser(CompilerInstance &Instance, IncrementalAction *Act, + llvm::Error &Err, std::list &PTUs); virtual ~IncrementalParser(); /// Parses incremental input by creating an in-memory file. @@ -57,6 +66,10 @@ class IncrementalParser { void CleanUpPTU(TranslationUnitDecl *MostRecentTU); + /// Register a PTU produced by Parse. + PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU, + std::unique_ptr M = {}); + private: llvm::Expected ParseOrWrapTopLevelDecl(); }; diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 5e5ae81b9ba44..47995216fac46 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "DeviceOffload.h" +#include "IncrementalAction.h" #include "IncrementalExecutor.h" #include "IncrementalParser.h" #include "InterpreterUtils.h" @@ -28,7 +29,6 @@ #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CodeGenAction.h" -#include "clang/CodeGen/ModuleBuilder.h" #include "clang/CodeGen/ObjectFilePCHContainerWriter.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" @@ -248,120 +248,6 @@ IncrementalCompilerBuilder::CreateCudaHost() { return IncrementalCompilerBuilder::createCuda(false); } -class InProcessPrintingASTConsumer final : public MultiplexConsumer { - Interpreter &Interp; - -public: - InProcessPrintingASTConsumer(std::unique_ptr C, Interpreter &I) - : MultiplexConsumer(std::move(C)), Interp(I) {} - bool HandleTopLevelDecl(DeclGroupRef DGR) override final { - if (DGR.isNull()) - return true; - - for (Decl *D : DGR) - if (auto *TLSD = llvm::dyn_cast(D)) - if (TLSD && TLSD->isSemiMissing()) { - auto ExprOrErr = - Interp.convertExprToValue(cast(TLSD->getStmt())); - if (llvm::Error E = ExprOrErr.takeError()) { - llvm::logAllUnhandledErrors(std::move(E), llvm::errs(), - "Value printing failed: "); - return false; // abort parsing - } - TLSD->setStmt(*ExprOrErr); - } - - return MultiplexConsumer::HandleTopLevelDecl(DGR); - } -}; - -/// A custom action enabling the incremental processing functionality. -/// -/// The usual \p FrontendAction expects one call to ExecuteAction and once it -/// sees a call to \p EndSourceFile it deletes some of the important objects -/// such as \p Preprocessor and \p Sema assuming no further input will come. -/// -/// \p IncrementalAction ensures it keep its underlying action's objects alive -/// as long as the \p IncrementalParser needs them. -/// -class IncrementalAction : public WrapperFrontendAction { -private: - bool IsTerminating = false; - Interpreter &Interp; - std::unique_ptr Consumer; - -public: - IncrementalAction(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx, - llvm::Error &Err, Interpreter &I, - std::unique_ptr Consumer = nullptr) - : WrapperFrontendAction([&]() { - llvm::ErrorAsOutParameter EAO(&Err); - std::unique_ptr Act; - switch (CI.getFrontendOpts().ProgramAction) { - default: - Err = llvm::createStringError( - std::errc::state_not_recoverable, - "Driver initialization failed. " - "Incremental mode for action %d is not supported", - CI.getFrontendOpts().ProgramAction); - return Act; - case frontend::ASTDump: - case frontend::ASTPrint: - case frontend::ParseSyntaxOnly: - Act = CreateFrontendAction(CI); - break; - case frontend::PluginAction: - case frontend::EmitAssembly: - case frontend::EmitBC: - case frontend::EmitObj: - case frontend::PrintPreprocessedInput: - case frontend::EmitLLVMOnly: - Act.reset(new EmitLLVMOnlyAction(&LLVMCtx)); - break; - } - return Act; - }()), - Interp(I), Consumer(std::move(Consumer)) {} - FrontendAction *getWrapped() const { return WrappedAction.get(); } - TranslationUnitKind getTranslationUnitKind() override { - return TU_Incremental; - } - - std::unique_ptr CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override { - std::unique_ptr C = - WrapperFrontendAction::CreateASTConsumer(CI, InFile); - - if (Consumer) { - std::vector> Cs; - Cs.push_back(std::move(Consumer)); - Cs.push_back(std::move(C)); - return std::make_unique(std::move(Cs)); - } - - return std::make_unique(std::move(C), Interp); - } - - void ExecuteAction() override { - WrapperFrontendAction::ExecuteAction(); - getCompilerInstance().getSema().CurContext = nullptr; - } - - // Do not terminate after processing the input. This allows us to keep various - // clang objects alive and to incrementally grow the current TU. - void EndSourceFile() override { - // The WrappedAction can be nullptr if we issued an error in the ctor. - if (IsTerminating && getWrapped()) - WrapperFrontendAction::EndSourceFile(); - } - - void FinalizeAction() { - assert(!IsTerminating && "Already finalized!"); - IsTerminating = true; - EndSourceFile(); - } -}; - Interpreter::Interpreter(std::unique_ptr Instance, llvm::Error &ErrOut, std::unique_ptr JITBuilder, @@ -381,22 +267,23 @@ Interpreter::Interpreter(std::unique_ptr Instance, return; CI->ExecuteAction(*Act); - IncrParser = std::make_unique(*CI, ErrOut); + IncrParser = + std::make_unique(*CI, Act.get(), ErrOut, PTUs); if (ErrOut) return; - if (getCodeGen()) { - CachedInCodeGenModule = GenModule(); + if (Act->getCodeGen()) { + Act->CacheCodeGenModule(); // The initial PTU is filled by `-include` or by CUDA includes // automatically. if (!CI->getPreprocessorOpts().Includes.empty()) { // We can't really directly pass the CachedInCodeGenModule to the Jit // because it will steal it, causing dangling references as explained in // Interpreter::Execute - auto M = llvm::CloneModule(*CachedInCodeGenModule); + auto M = llvm::CloneModule(*Act->getCachedCodeGenModule()); ASTContext &C = CI->getASTContext(); - RegisterPTU(C.getTranslationUnitDecl(), std::move(M)); + IncrParser->RegisterPTU(C.getTranslationUnitDecl(), std::move(M)); } if (llvm::Error Err = CreateExecutor()) { ErrOut = joinErrors(std::move(ErrOut), std::move(Err)); @@ -405,7 +292,7 @@ Interpreter::Interpreter(std::unique_ptr Instance, } // Not all frontends support code-generation, e.g. ast-dump actions don't - if (getCodeGen()) { + if (Act->getCodeGen()) { // Process the PTUs that came from initialization. For example -include will // give us a header that's processed at initialization of the preprocessor. for (PartialTranslationUnit &PTU : PTUs) @@ -515,8 +402,8 @@ Interpreter::createWithCUDA(std::unique_ptr CI, Interp->DeviceCI = std::move(DCI); auto DeviceParser = std::make_unique( - *Interp->DeviceCI, *Interp->getCompilerInstance(), IMVFS, Err, - Interp->PTUs); + *Interp->DeviceCI, *Interp->getCompilerInstance(), + Interp->DeviceAct.get(), IMVFS, Err, Interp->PTUs); if (Err) return std::move(Err); @@ -557,30 +444,6 @@ size_t Interpreter::getEffectivePTUSize() const { return PTUs.size() - InitPTUSize; } -PartialTranslationUnit & -Interpreter::RegisterPTU(TranslationUnitDecl *TU, - std::unique_ptr M /*={}*/, - IncrementalAction *Action) { - PTUs.emplace_back(PartialTranslationUnit()); - PartialTranslationUnit &LastPTU = PTUs.back(); - LastPTU.TUPart = TU; - - if (!M) - M = GenModule(Action); - - assert((!getCodeGen(Action) || M) && - "Must have a llvm::Module at this point"); - - LastPTU.TheModule = std::move(M); - LLVM_DEBUG(llvm::dbgs() << "compile-ptu " << PTUs.size() - 1 - << ": [TU=" << LastPTU.TUPart); - if (LastPTU.TheModule) - LLVM_DEBUG(llvm::dbgs() << ", M=" << LastPTU.TheModule.get() << " (" - << LastPTU.TheModule->getName() << ")"); - LLVM_DEBUG(llvm::dbgs() << "]\n"); - return LastPTU; -} - llvm::Expected Interpreter::Parse(llvm::StringRef Code) { // If we have a device parser, parse it first. The generated code will be @@ -590,7 +453,7 @@ Interpreter::Parse(llvm::StringRef Code) { if (auto E = DeviceTU.takeError()) return std::move(E); - RegisterPTU(*DeviceTU, nullptr, DeviceAct.get()); + DeviceParser->RegisterPTU(*DeviceTU); llvm::Expected PTX = DeviceParser->GeneratePTX(); if (!PTX) @@ -614,7 +477,7 @@ Interpreter::Parse(llvm::StringRef Code) { PartialTranslationUnit &LastPTU = PTUs.back(); LastPTU.TUPart = *TuOrErr; - if (std::unique_ptr M = GenModule()) + if (std::unique_ptr M = Act->GenModule()) LastPTU.TheModule = std::move(M); return LastPTU; @@ -654,7 +517,7 @@ llvm::Error Interpreter::CreateExecutor() { return llvm::make_error("Operation failed. " "Execution engine exists", std::error_code()); - if (!getCodeGen()) + if (!Act->getCodeGen()) return llvm::make_error("Operation failed. " "No code generator available", std::error_code()); @@ -733,7 +596,7 @@ Interpreter::getSymbolAddress(GlobalDecl GD) const { return llvm::make_error("Operation failed. " "No execution engine", std::error_code()); - llvm::StringRef MangledName = getCodeGen()->GetMangledName(GD); + llvm::StringRef MangledName = Act->getCodeGen()->GetMangledName(GD); return getSymbolAddress(MangledName); } @@ -809,38 +672,4 @@ llvm::Error Interpreter::LoadDynamicLibrary(const char *name) { return llvm::Error::success(); } - -std::unique_ptr -Interpreter::GenModule(IncrementalAction *Action) { - static unsigned ID = 0; - if (CodeGenerator *CG = getCodeGen(Action)) { - // Clang's CodeGen is designed to work with a single llvm::Module. In many - // cases for convenience various CodeGen parts have a reference to the - // llvm::Module (TheModule or Module) which does not change when a new - // module is pushed. However, the execution engine wants to take ownership - // of the module which does not map well to CodeGen's design. To work this - // around we created an empty module to make CodeGen happy. We should make - // sure it always stays empty. - assert(((!CachedInCodeGenModule || - !getCompilerInstance()->getPreprocessorOpts().Includes.empty()) || - ((CachedInCodeGenModule->empty() && - CachedInCodeGenModule->global_empty() && - CachedInCodeGenModule->alias_empty() && - CachedInCodeGenModule->ifunc_empty()))) && - "CodeGen wrote to a readonly module"); - std::unique_ptr M(CG->ReleaseModule()); - CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext()); - return M; - } - return nullptr; -} - -CodeGenerator *Interpreter::getCodeGen(IncrementalAction *Action) const { - if (!Action) - Action = Act.get(); - FrontendAction *WrappedAct = Action->getWrapped(); - if (!WrappedAct->hasIRSupport()) - return nullptr; - return static_cast(WrappedAct)->getCodeGenerator(); -} } // end namespace clang diff --git a/clang/lib/Interpreter/InterpreterValuePrinter.cpp b/clang/lib/Interpreter/InterpreterValuePrinter.cpp index 4f5f43e1b3ade..a329368fba144 100644 --- a/clang/lib/Interpreter/InterpreterValuePrinter.cpp +++ b/clang/lib/Interpreter/InterpreterValuePrinter.cpp @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -#include "IncrementalParser.h" +#include "IncrementalAction.h" #include "InterpreterUtils.h" #include "clang/AST/ASTContext.h" #include "clang/AST/PrettyPrinter.h" @@ -366,7 +366,7 @@ Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) const { getCompilerInstance()->getSema().LookupDestructor(CXXRD); llvm::StringRef Name = - getCodeGen()->GetMangledName(GlobalDecl(DtorRD, Dtor_Base)); + Act->getCodeGen()->GetMangledName(GlobalDecl(DtorRD, Dtor_Base)); auto AddrOrErr = getSymbolAddress(Name); if (!AddrOrErr) return AddrOrErr.takeError();