192f9852fSVassil Vassilev //===------ Interpreter.cpp - Incremental Compilation and Execution -------===// 292f9852fSVassil Vassilev // 392f9852fSVassil Vassilev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 492f9852fSVassil Vassilev // See https://llvm.org/LICENSE.txt for license information. 592f9852fSVassil Vassilev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 692f9852fSVassil Vassilev // 792f9852fSVassil Vassilev //===----------------------------------------------------------------------===// 892f9852fSVassil Vassilev // 992f9852fSVassil Vassilev // This file implements the component which performs incremental code 1092f9852fSVassil Vassilev // compilation and execution. 1192f9852fSVassil Vassilev // 1292f9852fSVassil Vassilev //===----------------------------------------------------------------------===// 1392f9852fSVassil Vassilev 14ddeab07cSAnubhab Ghosh #include "DeviceOffload.h" 1592f9852fSVassil Vassilev #include "IncrementalExecutor.h" 1692f9852fSVassil Vassilev #include "IncrementalParser.h" 17752f87cdSVassil Vassilev #include "InterpreterUtils.h" 18df9a14d7SKadir Cetinkaya #include "llvm/Support/VirtualFileSystem.h" 199a9546e3SVassil Vassilev #ifdef __EMSCRIPTEN__ 209a9546e3SVassil Vassilev #include "Wasm.h" 219a9546e3SVassil Vassilev #endif // __EMSCRIPTEN__ 2279af92bbSFred Fu 23a72d7eeaSVassil Vassilev #include "clang/AST/ASTConsumer.h" 2449f95321SVassil Vassilev #include "clang/AST/ASTContext.h" 255111286fSJun Zhang #include "clang/AST/Mangle.h" 265111286fSJun Zhang #include "clang/AST/TypeVisitor.h" 275111286fSJun Zhang #include "clang/Basic/DiagnosticSema.h" 2892f9852fSVassil Vassilev #include "clang/Basic/TargetInfo.h" 29ddeab07cSAnubhab Ghosh #include "clang/CodeGen/CodeGenAction.h" 3092f9852fSVassil Vassilev #include "clang/CodeGen/ModuleBuilder.h" 31d64eccf4SChuanqi Xu #include "clang/CodeGen/ObjectFilePCHContainerWriter.h" 3292f9852fSVassil Vassilev #include "clang/Driver/Compilation.h" 3392f9852fSVassil Vassilev #include "clang/Driver/Driver.h" 3492f9852fSVassil Vassilev #include "clang/Driver/Job.h" 3592f9852fSVassil Vassilev #include "clang/Driver/Options.h" 3692f9852fSVassil Vassilev #include "clang/Driver/Tool.h" 3792f9852fSVassil Vassilev #include "clang/Frontend/CompilerInstance.h" 38a72d7eeaSVassil Vassilev #include "clang/Frontend/FrontendAction.h" 39a72d7eeaSVassil Vassilev #include "clang/Frontend/MultiplexConsumer.h" 4092f9852fSVassil Vassilev #include "clang/Frontend/TextDiagnosticBuffer.h" 41a72d7eeaSVassil Vassilev #include "clang/FrontendTool/Utils.h" 4279af92bbSFred Fu #include "clang/Interpreter/Interpreter.h" 435111286fSJun Zhang #include "clang/Interpreter/Value.h" 4492f9852fSVassil Vassilev #include "clang/Lex/PreprocessorOptions.h" 455111286fSJun Zhang #include "clang/Sema/Lookup.h" 46d64eccf4SChuanqi Xu #include "clang/Serialization/ObjectFilePCHContainerReader.h" 475111286fSJun Zhang #include "llvm/ExecutionEngine/JITSymbol.h" 48d978730dSAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/LLJIT.h" 4992f9852fSVassil Vassilev #include "llvm/IR/Module.h" 506283d468SLuke Drummond #include "llvm/Support/Errc.h" 515111286fSJun Zhang #include "llvm/Support/ErrorHandling.h" 525111286fSJun Zhang #include "llvm/Support/raw_ostream.h" 53d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h" 54a8744066SVassil Vassilev #include "llvm/Transforms/Utils/Cloning.h" // for CloneModule 55a8744066SVassil Vassilev 56a8744066SVassil Vassilev #define DEBUG_TYPE "clang-repl" 577091dfc0SVassil Vassilev 5892f9852fSVassil Vassilev using namespace clang; 5992f9852fSVassil Vassilev // FIXME: Figure out how to unify with namespace init_convenience from 60c24a5808SVassil Vassilev // tools/clang-import-test/clang-import-test.cpp 6192f9852fSVassil Vassilev namespace { 6292f9852fSVassil Vassilev /// Retrieves the clang CC1 specific flags out of the compilation's jobs. 6392f9852fSVassil Vassilev /// \returns NULL on error. 6492f9852fSVassil Vassilev static llvm::Expected<const llvm::opt::ArgStringList *> 6592f9852fSVassil Vassilev GetCC1Arguments(DiagnosticsEngine *Diagnostics, 6692f9852fSVassil Vassilev driver::Compilation *Compilation) { 6792f9852fSVassil Vassilev // We expect to get back exactly one Command job, if we didn't something 6892f9852fSVassil Vassilev // failed. Extract that job from the Compilation. 6992f9852fSVassil Vassilev const driver::JobList &Jobs = Compilation->getJobs(); 7092f9852fSVassil Vassilev if (!Jobs.size() || !isa<driver::Command>(*Jobs.begin())) 716283d468SLuke Drummond return llvm::createStringError(llvm::errc::not_supported, 7292f9852fSVassil Vassilev "Driver initialization failed. " 7392f9852fSVassil Vassilev "Unable to create a driver job"); 7492f9852fSVassil Vassilev 7592f9852fSVassil Vassilev // The one job we find should be to invoke clang again. 7692f9852fSVassil Vassilev const driver::Command *Cmd = cast<driver::Command>(&(*Jobs.begin())); 7792f9852fSVassil Vassilev if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") 786283d468SLuke Drummond return llvm::createStringError(llvm::errc::not_supported, 7992f9852fSVassil Vassilev "Driver initialization failed"); 8092f9852fSVassil Vassilev 8192f9852fSVassil Vassilev return &Cmd->getArguments(); 8292f9852fSVassil Vassilev } 8392f9852fSVassil Vassilev 8492f9852fSVassil Vassilev static llvm::Expected<std::unique_ptr<CompilerInstance>> 8592f9852fSVassil Vassilev CreateCI(const llvm::opt::ArgStringList &Argv) { 8692f9852fSVassil Vassilev std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); 8792f9852fSVassil Vassilev IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 8892f9852fSVassil Vassilev 8992f9852fSVassil Vassilev // Register the support for object-file-wrapped Clang modules. 9092f9852fSVassil Vassilev // FIXME: Clang should register these container operations automatically. 9192f9852fSVassil Vassilev auto PCHOps = Clang->getPCHContainerOperations(); 9292f9852fSVassil Vassilev PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>()); 9392f9852fSVassil Vassilev PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>()); 9492f9852fSVassil Vassilev 9592f9852fSVassil Vassilev // Buffer diagnostics from argument parsing so that we can output them using 9692f9852fSVassil Vassilev // a well formed diagnostic object. 9792f9852fSVassil Vassilev IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 9892f9852fSVassil Vassilev TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; 9992f9852fSVassil Vassilev DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); 10092f9852fSVassil Vassilev bool Success = CompilerInvocation::CreateFromArgs( 101a3c248dbSserge-sans-paille Clang->getInvocation(), llvm::ArrayRef(Argv.begin(), Argv.size()), Diags); 10292f9852fSVassil Vassilev 10392f9852fSVassil Vassilev // Infer the builtin include path if unspecified. 10492f9852fSVassil Vassilev if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && 10592f9852fSVassil Vassilev Clang->getHeaderSearchOpts().ResourceDir.empty()) 10692f9852fSVassil Vassilev Clang->getHeaderSearchOpts().ResourceDir = 10792f9852fSVassil Vassilev CompilerInvocation::GetResourcesPath(Argv[0], nullptr); 10892f9852fSVassil Vassilev 10992f9852fSVassil Vassilev // Create the actual diagnostics engine. 110df9a14d7SKadir Cetinkaya Clang->createDiagnostics(*llvm::vfs::getRealFileSystem()); 11192f9852fSVassil Vassilev if (!Clang->hasDiagnostics()) 1126283d468SLuke Drummond return llvm::createStringError(llvm::errc::not_supported, 11392f9852fSVassil Vassilev "Initialization failed. " 11492f9852fSVassil Vassilev "Unable to create diagnostics engine"); 11592f9852fSVassil Vassilev 11692f9852fSVassil Vassilev DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics()); 11792f9852fSVassil Vassilev if (!Success) 1186283d468SLuke Drummond return llvm::createStringError(llvm::errc::not_supported, 11992f9852fSVassil Vassilev "Initialization failed. " 12092f9852fSVassil Vassilev "Unable to flush diagnostics"); 12192f9852fSVassil Vassilev 12292f9852fSVassil Vassilev // FIXME: Merge with CompilerInstance::ExecuteAction. 12392f9852fSVassil Vassilev llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release(); 12492f9852fSVassil Vassilev Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB); 12592f9852fSVassil Vassilev 12692f9852fSVassil Vassilev Clang->setTarget(TargetInfo::CreateTargetInfo( 12792f9852fSVassil Vassilev Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); 12892f9852fSVassil Vassilev if (!Clang->hasTarget()) 1296283d468SLuke Drummond return llvm::createStringError(llvm::errc::not_supported, 13092f9852fSVassil Vassilev "Initialization failed. " 13192f9852fSVassil Vassilev "Target is missing"); 13292f9852fSVassil Vassilev 133aaba3718SMelanie Blower Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts()); 13492f9852fSVassil Vassilev 13519b07ec0SArthur Eubanks // Don't clear the AST before backend codegen since we do codegen multiple 13619b07ec0SArthur Eubanks // times, reusing the same AST. 13719b07ec0SArthur Eubanks Clang->getCodeGenOpts().ClearASTBeforeBackend = false; 13819b07ec0SArthur Eubanks 1397bc00ce5SSunho Kim Clang->getFrontendOpts().DisableFree = false; 1407bc00ce5SSunho Kim Clang->getCodeGenOpts().DisableFree = false; 14192f9852fSVassil Vassilev return std::move(Clang); 14292f9852fSVassil Vassilev } 14392f9852fSVassil Vassilev 14492f9852fSVassil Vassilev } // anonymous namespace 14592f9852fSVassil Vassilev 146a72d7eeaSVassil Vassilev namespace clang { 147a72d7eeaSVassil Vassilev 14892f9852fSVassil Vassilev llvm::Expected<std::unique_ptr<CompilerInstance>> 1492a4a852aSStefan Gränitz IncrementalCompilerBuilder::create(std::string TT, 1502a4a852aSStefan Gränitz std::vector<const char *> &ClangArgv) { 15192f9852fSVassil Vassilev 15292f9852fSVassil Vassilev // If we don't know ClangArgv0 or the address of main() at this point, try 15392f9852fSVassil Vassilev // to guess it anyway (it's possible on some platforms). 15492f9852fSVassil Vassilev std::string MainExecutableName = 15592f9852fSVassil Vassilev llvm::sys::fs::getMainExecutable(nullptr, nullptr); 15692f9852fSVassil Vassilev 15792f9852fSVassil Vassilev ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str()); 15892f9852fSVassil Vassilev 15992f9852fSVassil Vassilev // Prepending -c to force the driver to do something if no action was 16092f9852fSVassil Vassilev // specified. By prepending we allow users to override the default 16192f9852fSVassil Vassilev // action and use other actions in incremental mode. 16292f9852fSVassil Vassilev // FIXME: Print proper driver diagnostics if the driver flags are wrong. 16392f9852fSVassil Vassilev // We do C++ by default; append right after argv[0] if no "-x" given 164dc488935SVassil Vassilev ClangArgv.insert(ClangArgv.end(), "-Xclang"); 165dc488935SVassil Vassilev ClangArgv.insert(ClangArgv.end(), "-fincremental-extensions"); 166dc488935SVassil Vassilev ClangArgv.insert(ClangArgv.end(), "-c"); 16792f9852fSVassil Vassilev 16892f9852fSVassil Vassilev // Put a dummy C++ file on to ensure there's at least one compile job for the 16992f9852fSVassil Vassilev // driver to construct. 17092f9852fSVassil Vassilev ClangArgv.push_back("<<< inputs >>>"); 17192f9852fSVassil Vassilev 17292f9852fSVassil Vassilev // Buffer diagnostics from argument parsing so that we can output them using a 17392f9852fSVassil Vassilev // well formed diagnostic object. 17492f9852fSVassil Vassilev IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 175555a817dSJan Svoboda IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = 176555a817dSJan Svoboda CreateAndPopulateDiagOpts(ClangArgv); 17792f9852fSVassil Vassilev TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; 17892f9852fSVassil Vassilev DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); 17992f9852fSVassil Vassilev 1802a4a852aSStefan Gränitz driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags); 18192f9852fSVassil Vassilev Driver.setCheckInputsExist(false); // the input comes from mem buffers 182a3c248dbSserge-sans-paille llvm::ArrayRef<const char *> RF = llvm::ArrayRef(ClangArgv); 18392f9852fSVassil Vassilev std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF)); 18492f9852fSVassil Vassilev 18592f9852fSVassil Vassilev if (Compilation->getArgs().hasArg(driver::options::OPT_v)) 18692f9852fSVassil Vassilev Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false); 18792f9852fSVassil Vassilev 18892f9852fSVassil Vassilev auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get()); 18992f9852fSVassil Vassilev if (auto Err = ErrOrCC1Args.takeError()) 19092f9852fSVassil Vassilev return std::move(Err); 19192f9852fSVassil Vassilev 19292f9852fSVassil Vassilev return CreateCI(**ErrOrCC1Args); 19392f9852fSVassil Vassilev } 19492f9852fSVassil Vassilev 195ddeab07cSAnubhab Ghosh llvm::Expected<std::unique_ptr<CompilerInstance>> 196ddeab07cSAnubhab Ghosh IncrementalCompilerBuilder::CreateCpp() { 197ddeab07cSAnubhab Ghosh std::vector<const char *> Argv; 198ddeab07cSAnubhab Ghosh Argv.reserve(5 + 1 + UserArgs.size()); 199ddeab07cSAnubhab Ghosh Argv.push_back("-xc++"); 2009a9546e3SVassil Vassilev #ifdef __EMSCRIPTEN__ 2019a9546e3SVassil Vassilev Argv.push_back("-target"); 2029a9546e3SVassil Vassilev Argv.push_back("wasm32-unknown-emscripten"); 203a174aa1eSAnutosh Bhat Argv.push_back("-fvisibility=default"); 2049a9546e3SVassil Vassilev #endif 205ddeab07cSAnubhab Ghosh Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end()); 206ddeab07cSAnubhab Ghosh 2072a4a852aSStefan Gränitz std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple(); 2082a4a852aSStefan Gränitz return IncrementalCompilerBuilder::create(TT, Argv); 209ddeab07cSAnubhab Ghosh } 210ddeab07cSAnubhab Ghosh 211ddeab07cSAnubhab Ghosh llvm::Expected<std::unique_ptr<CompilerInstance>> 212ddeab07cSAnubhab Ghosh IncrementalCompilerBuilder::createCuda(bool device) { 213ddeab07cSAnubhab Ghosh std::vector<const char *> Argv; 214ddeab07cSAnubhab Ghosh Argv.reserve(5 + 4 + UserArgs.size()); 215ddeab07cSAnubhab Ghosh 216ddeab07cSAnubhab Ghosh Argv.push_back("-xcuda"); 217ddeab07cSAnubhab Ghosh if (device) 218ddeab07cSAnubhab Ghosh Argv.push_back("--cuda-device-only"); 219ddeab07cSAnubhab Ghosh else 220ddeab07cSAnubhab Ghosh Argv.push_back("--cuda-host-only"); 221ddeab07cSAnubhab Ghosh 222ddeab07cSAnubhab Ghosh std::string SDKPathArg = "--cuda-path="; 223ddeab07cSAnubhab Ghosh if (!CudaSDKPath.empty()) { 224ddeab07cSAnubhab Ghosh SDKPathArg += CudaSDKPath; 225ddeab07cSAnubhab Ghosh Argv.push_back(SDKPathArg.c_str()); 226ddeab07cSAnubhab Ghosh } 227ddeab07cSAnubhab Ghosh 228ddeab07cSAnubhab Ghosh std::string ArchArg = "--offload-arch="; 229ddeab07cSAnubhab Ghosh if (!OffloadArch.empty()) { 230ddeab07cSAnubhab Ghosh ArchArg += OffloadArch; 231ddeab07cSAnubhab Ghosh Argv.push_back(ArchArg.c_str()); 232ddeab07cSAnubhab Ghosh } 233ddeab07cSAnubhab Ghosh 234ddeab07cSAnubhab Ghosh Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end()); 235ddeab07cSAnubhab Ghosh 2362a4a852aSStefan Gränitz std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple(); 2372a4a852aSStefan Gränitz return IncrementalCompilerBuilder::create(TT, Argv); 238ddeab07cSAnubhab Ghosh } 239ddeab07cSAnubhab Ghosh 240ddeab07cSAnubhab Ghosh llvm::Expected<std::unique_ptr<CompilerInstance>> 241ddeab07cSAnubhab Ghosh IncrementalCompilerBuilder::CreateCudaDevice() { 242ddeab07cSAnubhab Ghosh return IncrementalCompilerBuilder::createCuda(true); 243ddeab07cSAnubhab Ghosh } 244ddeab07cSAnubhab Ghosh 245ddeab07cSAnubhab Ghosh llvm::Expected<std::unique_ptr<CompilerInstance>> 246ddeab07cSAnubhab Ghosh IncrementalCompilerBuilder::CreateCudaHost() { 247ddeab07cSAnubhab Ghosh return IncrementalCompilerBuilder::createCuda(false); 248ddeab07cSAnubhab Ghosh } 249ddeab07cSAnubhab Ghosh 250a72d7eeaSVassil Vassilev class InProcessPrintingASTConsumer final : public MultiplexConsumer { 251a72d7eeaSVassil Vassilev Interpreter &Interp; 252a72d7eeaSVassil Vassilev 253a72d7eeaSVassil Vassilev public: 254a72d7eeaSVassil Vassilev InProcessPrintingASTConsumer(std::unique_ptr<ASTConsumer> C, Interpreter &I) 255a72d7eeaSVassil Vassilev : MultiplexConsumer(std::move(C)), Interp(I) {} 256a72d7eeaSVassil Vassilev bool HandleTopLevelDecl(DeclGroupRef DGR) override final { 257a72d7eeaSVassil Vassilev if (DGR.isNull()) 258a72d7eeaSVassil Vassilev return true; 259a72d7eeaSVassil Vassilev 260a72d7eeaSVassil Vassilev for (Decl *D : DGR) 261a72d7eeaSVassil Vassilev if (auto *TLSD = llvm::dyn_cast<TopLevelStmtDecl>(D)) 262a72d7eeaSVassil Vassilev if (TLSD && TLSD->isSemiMissing()) { 263a72d7eeaSVassil Vassilev auto ExprOrErr = 264a72d7eeaSVassil Vassilev Interp.ExtractValueFromExpr(cast<Expr>(TLSD->getStmt())); 265a72d7eeaSVassil Vassilev if (llvm::Error E = ExprOrErr.takeError()) { 266a72d7eeaSVassil Vassilev llvm::logAllUnhandledErrors(std::move(E), llvm::errs(), 267a72d7eeaSVassil Vassilev "Value printing failed: "); 268a72d7eeaSVassil Vassilev return false; // abort parsing 269a72d7eeaSVassil Vassilev } 270a72d7eeaSVassil Vassilev TLSD->setStmt(*ExprOrErr); 271a72d7eeaSVassil Vassilev } 272a72d7eeaSVassil Vassilev 273a72d7eeaSVassil Vassilev return MultiplexConsumer::HandleTopLevelDecl(DGR); 274a72d7eeaSVassil Vassilev } 275a72d7eeaSVassil Vassilev }; 276a72d7eeaSVassil Vassilev 277a72d7eeaSVassil Vassilev /// A custom action enabling the incremental processing functionality. 278a72d7eeaSVassil Vassilev /// 279a72d7eeaSVassil Vassilev /// The usual \p FrontendAction expects one call to ExecuteAction and once it 280a72d7eeaSVassil Vassilev /// sees a call to \p EndSourceFile it deletes some of the important objects 281a72d7eeaSVassil Vassilev /// such as \p Preprocessor and \p Sema assuming no further input will come. 282a72d7eeaSVassil Vassilev /// 283a72d7eeaSVassil Vassilev /// \p IncrementalAction ensures it keep its underlying action's objects alive 284a72d7eeaSVassil Vassilev /// as long as the \p IncrementalParser needs them. 285a72d7eeaSVassil Vassilev /// 286a72d7eeaSVassil Vassilev class IncrementalAction : public WrapperFrontendAction { 287a72d7eeaSVassil Vassilev private: 288a72d7eeaSVassil Vassilev bool IsTerminating = false; 289a72d7eeaSVassil Vassilev Interpreter &Interp; 290a72d7eeaSVassil Vassilev std::unique_ptr<ASTConsumer> Consumer; 291a72d7eeaSVassil Vassilev 292a72d7eeaSVassil Vassilev public: 293a72d7eeaSVassil Vassilev IncrementalAction(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx, 294a72d7eeaSVassil Vassilev llvm::Error &Err, Interpreter &I, 295a72d7eeaSVassil Vassilev std::unique_ptr<ASTConsumer> Consumer = nullptr) 296a72d7eeaSVassil Vassilev : WrapperFrontendAction([&]() { 297a72d7eeaSVassil Vassilev llvm::ErrorAsOutParameter EAO(&Err); 298a72d7eeaSVassil Vassilev std::unique_ptr<FrontendAction> Act; 299a72d7eeaSVassil Vassilev switch (CI.getFrontendOpts().ProgramAction) { 300a72d7eeaSVassil Vassilev default: 301a72d7eeaSVassil Vassilev Err = llvm::createStringError( 302a72d7eeaSVassil Vassilev std::errc::state_not_recoverable, 303a72d7eeaSVassil Vassilev "Driver initialization failed. " 304a72d7eeaSVassil Vassilev "Incremental mode for action %d is not supported", 305a72d7eeaSVassil Vassilev CI.getFrontendOpts().ProgramAction); 306a72d7eeaSVassil Vassilev return Act; 307a72d7eeaSVassil Vassilev case frontend::ASTDump: 308a72d7eeaSVassil Vassilev case frontend::ASTPrint: 309a72d7eeaSVassil Vassilev case frontend::ParseSyntaxOnly: 310a72d7eeaSVassil Vassilev Act = CreateFrontendAction(CI); 311a72d7eeaSVassil Vassilev break; 312a72d7eeaSVassil Vassilev case frontend::PluginAction: 313a72d7eeaSVassil Vassilev case frontend::EmitAssembly: 314a72d7eeaSVassil Vassilev case frontend::EmitBC: 315a72d7eeaSVassil Vassilev case frontend::EmitObj: 316a72d7eeaSVassil Vassilev case frontend::PrintPreprocessedInput: 317a72d7eeaSVassil Vassilev case frontend::EmitLLVMOnly: 318a72d7eeaSVassil Vassilev Act.reset(new EmitLLVMOnlyAction(&LLVMCtx)); 319a72d7eeaSVassil Vassilev break; 320a72d7eeaSVassil Vassilev } 321a72d7eeaSVassil Vassilev return Act; 322a72d7eeaSVassil Vassilev }()), 323a72d7eeaSVassil Vassilev Interp(I), Consumer(std::move(Consumer)) {} 324a72d7eeaSVassil Vassilev FrontendAction *getWrapped() const { return WrappedAction.get(); } 325a72d7eeaSVassil Vassilev TranslationUnitKind getTranslationUnitKind() override { 326a72d7eeaSVassil Vassilev return TU_Incremental; 327a72d7eeaSVassil Vassilev } 328a72d7eeaSVassil Vassilev 329a72d7eeaSVassil Vassilev std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, 330a72d7eeaSVassil Vassilev StringRef InFile) override { 331a72d7eeaSVassil Vassilev std::unique_ptr<ASTConsumer> C = 332a72d7eeaSVassil Vassilev WrapperFrontendAction::CreateASTConsumer(CI, InFile); 333a72d7eeaSVassil Vassilev 334a72d7eeaSVassil Vassilev if (Consumer) { 335a72d7eeaSVassil Vassilev std::vector<std::unique_ptr<ASTConsumer>> Cs; 336a72d7eeaSVassil Vassilev Cs.push_back(std::move(Consumer)); 337a72d7eeaSVassil Vassilev Cs.push_back(std::move(C)); 338a72d7eeaSVassil Vassilev return std::make_unique<MultiplexConsumer>(std::move(Cs)); 339a72d7eeaSVassil Vassilev } 340a72d7eeaSVassil Vassilev 341a72d7eeaSVassil Vassilev return std::make_unique<InProcessPrintingASTConsumer>(std::move(C), Interp); 342a72d7eeaSVassil Vassilev } 343a72d7eeaSVassil Vassilev 344a72d7eeaSVassil Vassilev void ExecuteAction() override { 345a8744066SVassil Vassilev WrapperFrontendAction::ExecuteAction(); 346a8744066SVassil Vassilev getCompilerInstance().getSema().CurContext = nullptr; 347a72d7eeaSVassil Vassilev } 348a72d7eeaSVassil Vassilev 349a72d7eeaSVassil Vassilev // Do not terminate after processing the input. This allows us to keep various 350a72d7eeaSVassil Vassilev // clang objects alive and to incrementally grow the current TU. 351a72d7eeaSVassil Vassilev void EndSourceFile() override { 352a72d7eeaSVassil Vassilev // The WrappedAction can be nullptr if we issued an error in the ctor. 353a72d7eeaSVassil Vassilev if (IsTerminating && getWrapped()) 354a72d7eeaSVassil Vassilev WrapperFrontendAction::EndSourceFile(); 355a72d7eeaSVassil Vassilev } 356a72d7eeaSVassil Vassilev 357a72d7eeaSVassil Vassilev void FinalizeAction() { 358a72d7eeaSVassil Vassilev assert(!IsTerminating && "Already finalized!"); 359a72d7eeaSVassil Vassilev IsTerminating = true; 360a72d7eeaSVassil Vassilev EndSourceFile(); 361a72d7eeaSVassil Vassilev } 362a72d7eeaSVassil Vassilev }; 363a72d7eeaSVassil Vassilev 364a72d7eeaSVassil Vassilev Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance, 365cb7995a1SStefan Gränitz llvm::Error &ErrOut, 366a72d7eeaSVassil Vassilev std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder, 367a72d7eeaSVassil Vassilev std::unique_ptr<clang::ASTConsumer> Consumer) 368cb7995a1SStefan Gränitz : JITBuilder(std::move(JITBuilder)) { 369a72d7eeaSVassil Vassilev CI = std::move(Instance); 370cb7995a1SStefan Gränitz llvm::ErrorAsOutParameter EAO(&ErrOut); 37192f9852fSVassil Vassilev auto LLVMCtx = std::make_unique<llvm::LLVMContext>(); 37292f9852fSVassil Vassilev TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx)); 373a72d7eeaSVassil Vassilev 374a72d7eeaSVassil Vassilev Act = std::make_unique<IncrementalAction>(*CI, *TSCtx->getContext(), ErrOut, 375a72d7eeaSVassil Vassilev *this, std::move(Consumer)); 376a72d7eeaSVassil Vassilev if (ErrOut) 377a72d7eeaSVassil Vassilev return; 378a72d7eeaSVassil Vassilev CI->ExecuteAction(*Act); 379a72d7eeaSVassil Vassilev 380a72d7eeaSVassil Vassilev IncrParser = std::make_unique<IncrementalParser>(*CI, ErrOut); 381a72d7eeaSVassil Vassilev 382cb7995a1SStefan Gränitz if (ErrOut) 383cb7995a1SStefan Gränitz return; 384cb7995a1SStefan Gränitz 385a72d7eeaSVassil Vassilev if (getCodeGen()) { 386a72d7eeaSVassil Vassilev CachedInCodeGenModule = GenModule(); 387a8744066SVassil Vassilev // The initial PTU is filled by `-include` or by CUDA includes 388a8744066SVassil Vassilev // automatically. 389a8744066SVassil Vassilev if (!CI->getPreprocessorOpts().Includes.empty()) { 390a8744066SVassil Vassilev // We can't really directly pass the CachedInCodeGenModule to the Jit 391a8744066SVassil Vassilev // because it will steal it, causing dangling references as explained in 392a8744066SVassil Vassilev // Interpreter::Execute 393a8744066SVassil Vassilev auto M = llvm::CloneModule(*CachedInCodeGenModule); 394a8744066SVassil Vassilev ASTContext &C = CI->getASTContext(); 395a8744066SVassil Vassilev RegisterPTU(C.getTranslationUnitDecl(), std::move(M)); 396a8744066SVassil Vassilev } 397cb7995a1SStefan Gränitz if (llvm::Error Err = CreateExecutor()) { 398cb7995a1SStefan Gränitz ErrOut = joinErrors(std::move(ErrOut), std::move(Err)); 399cb7995a1SStefan Gränitz return; 400cb7995a1SStefan Gränitz } 401a72d7eeaSVassil Vassilev } 402cb7995a1SStefan Gränitz 403a72d7eeaSVassil Vassilev // Not all frontends support code-generation, e.g. ast-dump actions don't 404a72d7eeaSVassil Vassilev if (getCodeGen()) { 405cb7995a1SStefan Gränitz // Process the PTUs that came from initialization. For example -include will 406cb7995a1SStefan Gränitz // give us a header that's processed at initialization of the preprocessor. 407a72d7eeaSVassil Vassilev for (PartialTranslationUnit &PTU : PTUs) 408cb7995a1SStefan Gränitz if (llvm::Error Err = Execute(PTU)) { 409cb7995a1SStefan Gränitz ErrOut = joinErrors(std::move(ErrOut), std::move(Err)); 410cb7995a1SStefan Gränitz return; 411cb7995a1SStefan Gränitz } 412cb7995a1SStefan Gränitz } 41392f9852fSVassil Vassilev } 41492f9852fSVassil Vassilev 415c619d4f8SSunho Kim Interpreter::~Interpreter() { 416a72d7eeaSVassil Vassilev IncrParser.reset(); 417a72d7eeaSVassil Vassilev Act->FinalizeAction(); 418c619d4f8SSunho Kim if (IncrExecutor) { 419c619d4f8SSunho Kim if (llvm::Error Err = IncrExecutor->cleanUp()) 420c619d4f8SSunho Kim llvm::report_fatal_error( 421c619d4f8SSunho Kim llvm::Twine("Failed to clean up IncrementalExecutor: ") + 422c619d4f8SSunho Kim toString(std::move(Err))); 423c619d4f8SSunho Kim } 424c619d4f8SSunho Kim } 42592f9852fSVassil Vassilev 4265111286fSJun Zhang // These better to put in a runtime header but we can't. This is because we 4275111286fSJun Zhang // can't find the precise resource directory in unittests so we have to hard 4285111286fSJun Zhang // code them. 4295111286fSJun Zhang const char *const Runtimes = R"( 4307091dfc0SVassil Vassilev #define __CLANG_REPL__ 1 4311566f1ffSVassil Vassilev #ifdef __cplusplus 4327091dfc0SVassil Vassilev #define EXTERN_C extern "C" 4335111286fSJun Zhang void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*); 4341566f1ffSVassil Vassilev struct __clang_Interpreter_NewTag{} __ci_newtag; 4351566f1ffSVassil Vassilev void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept; 4365111286fSJun Zhang template <class T, class = T (*)() /*disable for arrays*/> 4375111286fSJun Zhang void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) { 4385111286fSJun Zhang for (auto Idx = 0; Idx < Size; ++Idx) 4391566f1ffSVassil Vassilev new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]); 4405111286fSJun Zhang } 4415111286fSJun Zhang template <class T, unsigned long N> 4425111286fSJun Zhang void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) { 4435111286fSJun Zhang __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size); 4445111286fSJun Zhang } 4457091dfc0SVassil Vassilev #else 4467091dfc0SVassil Vassilev #define EXTERN_C extern 4471566f1ffSVassil Vassilev #endif // __cplusplus 4487091dfc0SVassil Vassilev 4497091dfc0SVassil Vassilev EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...); 4505111286fSJun Zhang )"; 4515111286fSJun Zhang 45292f9852fSVassil Vassilev llvm::Expected<std::unique_ptr<Interpreter>> 453ebb35088SSahilPatidar Interpreter::create(std::unique_ptr<CompilerInstance> CI) { 45492f9852fSVassil Vassilev llvm::Error Err = llvm::Error::success(); 455ebb35088SSahilPatidar auto Interp = 456ebb35088SSahilPatidar std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err)); 45792f9852fSVassil Vassilev if (Err) 45892f9852fSVassil Vassilev return std::move(Err); 45979af92bbSFred Fu 460aec92830SStefan Gränitz // Add runtime code and set a marker to hide it from user code. Undo will not 461aec92830SStefan Gränitz // go through that. 4625111286fSJun Zhang auto PTU = Interp->Parse(Runtimes); 4635111286fSJun Zhang if (!PTU) 4645111286fSJun Zhang return PTU.takeError(); 465aec92830SStefan Gränitz Interp->markUserCodeStart(); 4665111286fSJun Zhang 4671566f1ffSVassil Vassilev Interp->ValuePrintingInfo.resize(4); 46892f9852fSVassil Vassilev return std::move(Interp); 46992f9852fSVassil Vassilev } 47092f9852fSVassil Vassilev 471ddeab07cSAnubhab Ghosh llvm::Expected<std::unique_ptr<Interpreter>> 472ddeab07cSAnubhab Ghosh Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI, 473ddeab07cSAnubhab Ghosh std::unique_ptr<CompilerInstance> DCI) { 474ddeab07cSAnubhab Ghosh // avoid writing fat binary to disk using an in-memory virtual file system 475ddeab07cSAnubhab Ghosh llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> IMVFS = 476ddeab07cSAnubhab Ghosh std::make_unique<llvm::vfs::InMemoryFileSystem>(); 477ddeab07cSAnubhab Ghosh llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS = 478ddeab07cSAnubhab Ghosh std::make_unique<llvm::vfs::OverlayFileSystem>( 479ddeab07cSAnubhab Ghosh llvm::vfs::getRealFileSystem()); 480ddeab07cSAnubhab Ghosh OverlayVFS->pushOverlay(IMVFS); 481ddeab07cSAnubhab Ghosh CI->createFileManager(OverlayVFS); 482ddeab07cSAnubhab Ghosh 483ddeab07cSAnubhab Ghosh auto Interp = Interpreter::create(std::move(CI)); 484ddeab07cSAnubhab Ghosh if (auto E = Interp.takeError()) 485ddeab07cSAnubhab Ghosh return std::move(E); 486ddeab07cSAnubhab Ghosh 487ddeab07cSAnubhab Ghosh llvm::Error Err = llvm::Error::success(); 488ddeab07cSAnubhab Ghosh auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>( 489a72d7eeaSVassil Vassilev std::move(DCI), *(*Interp)->getCompilerInstance(), IMVFS, Err, 490a72d7eeaSVassil Vassilev (*Interp)->PTUs); 491ddeab07cSAnubhab Ghosh if (Err) 492ddeab07cSAnubhab Ghosh return std::move(Err); 493ddeab07cSAnubhab Ghosh 494ddeab07cSAnubhab Ghosh (*Interp)->DeviceParser = std::move(DeviceParser); 495ddeab07cSAnubhab Ghosh 496ddeab07cSAnubhab Ghosh return Interp; 497ddeab07cSAnubhab Ghosh } 498ddeab07cSAnubhab Ghosh 49992f9852fSVassil Vassilev const CompilerInstance *Interpreter::getCompilerInstance() const { 500a72d7eeaSVassil Vassilev return CI.get(); 50192f9852fSVassil Vassilev } 50292f9852fSVassil Vassilev 503a72d7eeaSVassil Vassilev CompilerInstance *Interpreter::getCompilerInstance() { return CI.get(); } 50435b366acSFred Fu 505d978730dSAnubhab Ghosh llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() { 506d978730dSAnubhab Ghosh if (!IncrExecutor) { 507d978730dSAnubhab Ghosh if (auto Err = CreateExecutor()) 508766d048dSAnubhab Ghosh return std::move(Err); 509d978730dSAnubhab Ghosh } 510d978730dSAnubhab Ghosh 511d978730dSAnubhab Ghosh return IncrExecutor->GetExecutionEngine(); 512788e0f7fSVassil Vassilev } 513788e0f7fSVassil Vassilev 5145111286fSJun Zhang ASTContext &Interpreter::getASTContext() { 5155111286fSJun Zhang return getCompilerInstance()->getASTContext(); 5165111286fSJun Zhang } 5175111286fSJun Zhang 5185111286fSJun Zhang const ASTContext &Interpreter::getASTContext() const { 5195111286fSJun Zhang return getCompilerInstance()->getASTContext(); 5205111286fSJun Zhang } 5215111286fSJun Zhang 522aec92830SStefan Gränitz void Interpreter::markUserCodeStart() { 523aec92830SStefan Gränitz assert(!InitPTUSize && "We only do this once"); 524a72d7eeaSVassil Vassilev InitPTUSize = PTUs.size(); 525aec92830SStefan Gränitz } 526aec92830SStefan Gränitz 5275111286fSJun Zhang size_t Interpreter::getEffectivePTUSize() const { 5285111286fSJun Zhang assert(PTUs.size() >= InitPTUSize && "empty PTU list?"); 5295111286fSJun Zhang return PTUs.size() - InitPTUSize; 5305111286fSJun Zhang } 5315111286fSJun Zhang 532a8744066SVassil Vassilev PartialTranslationUnit & 533a8744066SVassil Vassilev Interpreter::RegisterPTU(TranslationUnitDecl *TU, 534a8744066SVassil Vassilev std::unique_ptr<llvm::Module> M /*={}*/) { 535a72d7eeaSVassil Vassilev PTUs.emplace_back(PartialTranslationUnit()); 536a72d7eeaSVassil Vassilev PartialTranslationUnit &LastPTU = PTUs.back(); 537a72d7eeaSVassil Vassilev LastPTU.TUPart = TU; 538a72d7eeaSVassil Vassilev 539a8744066SVassil Vassilev if (!M) 540a8744066SVassil Vassilev M = GenModule(); 541a72d7eeaSVassil Vassilev 542a8744066SVassil Vassilev assert((!getCodeGen() || M) && "Must have a llvm::Module at this point"); 543a8744066SVassil Vassilev 544a8744066SVassil Vassilev LastPTU.TheModule = std::move(M); 545a8744066SVassil Vassilev LLVM_DEBUG(llvm::dbgs() << "compile-ptu " << PTUs.size() - 1 546a8744066SVassil Vassilev << ": [TU=" << LastPTU.TUPart); 547a8744066SVassil Vassilev if (LastPTU.TheModule) 548a8744066SVassil Vassilev LLVM_DEBUG(llvm::dbgs() << ", M=" << LastPTU.TheModule.get() << " (" 549a8744066SVassil Vassilev << LastPTU.TheModule->getName() << ")"); 550a8744066SVassil Vassilev LLVM_DEBUG(llvm::dbgs() << "]\n"); 551a72d7eeaSVassil Vassilev return LastPTU; 552a72d7eeaSVassil Vassilev } 553a72d7eeaSVassil Vassilev 55411b47c10SVassil Vassilev llvm::Expected<PartialTranslationUnit &> 55511b47c10SVassil Vassilev Interpreter::Parse(llvm::StringRef Code) { 556a72d7eeaSVassil Vassilev // If we have a device parser, parse it first. The generated code will be 557a72d7eeaSVassil Vassilev // included in the host compilation 558ddeab07cSAnubhab Ghosh if (DeviceParser) { 559a72d7eeaSVassil Vassilev llvm::Expected<TranslationUnitDecl *> DeviceTU = DeviceParser->Parse(Code); 560a72d7eeaSVassil Vassilev if (auto E = DeviceTU.takeError()) 561ddeab07cSAnubhab Ghosh return std::move(E); 562ddeab07cSAnubhab Ghosh } 563ddeab07cSAnubhab Ghosh 5645111286fSJun Zhang // Tell the interpreter sliently ignore unused expressions since value 5655111286fSJun Zhang // printing could cause it. 5665111286fSJun Zhang getCompilerInstance()->getDiagnostics().setSeverity( 5675111286fSJun Zhang clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation()); 568a72d7eeaSVassil Vassilev 569a72d7eeaSVassil Vassilev llvm::Expected<TranslationUnitDecl *> TuOrErr = IncrParser->Parse(Code); 570a72d7eeaSVassil Vassilev if (!TuOrErr) 571a72d7eeaSVassil Vassilev return TuOrErr.takeError(); 572a72d7eeaSVassil Vassilev 573a72d7eeaSVassil Vassilev return RegisterPTU(*TuOrErr); 57492f9852fSVassil Vassilev } 57592f9852fSVassil Vassilev 5760cf4788dSStefan Gränitz static llvm::Expected<llvm::orc::JITTargetMachineBuilder> 5770cf4788dSStefan Gränitz createJITTargetMachineBuilder(const std::string &TT) { 5780cf4788dSStefan Gränitz if (TT == llvm::sys::getProcessTriple()) 5790cf4788dSStefan Gränitz // This fails immediately if the target backend is not registered 5800cf4788dSStefan Gränitz return llvm::orc::JITTargetMachineBuilder::detectHost(); 5810cf4788dSStefan Gränitz 5820cf4788dSStefan Gränitz // If the target backend is not registered, LLJITBuilder::create() will fail 5830cf4788dSStefan Gränitz return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT)); 5840cf4788dSStefan Gränitz } 5850cf4788dSStefan Gränitz 586d978730dSAnubhab Ghosh llvm::Error Interpreter::CreateExecutor() { 587bde7a6b7SStefan Gränitz if (IncrExecutor) 588bde7a6b7SStefan Gränitz return llvm::make_error<llvm::StringError>("Operation failed. " 589bde7a6b7SStefan Gränitz "Execution engine exists", 590bde7a6b7SStefan Gränitz std::error_code()); 591a72d7eeaSVassil Vassilev if (!getCodeGen()) 592cb7995a1SStefan Gränitz return llvm::make_error<llvm::StringError>("Operation failed. " 593cb7995a1SStefan Gränitz "No code generator available", 594cb7995a1SStefan Gränitz std::error_code()); 595cb7995a1SStefan Gränitz if (!JITBuilder) { 596cb7995a1SStefan Gränitz const std::string &TT = getCompilerInstance()->getTargetOpts().Triple; 597cb7995a1SStefan Gränitz auto JTMB = createJITTargetMachineBuilder(TT); 598cb7995a1SStefan Gränitz if (!JTMB) 599cb7995a1SStefan Gränitz return JTMB.takeError(); 600cb7995a1SStefan Gränitz auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB)); 6010cf4788dSStefan Gränitz if (!JB) 6020cf4788dSStefan Gränitz return JB.takeError(); 603cb7995a1SStefan Gränitz JITBuilder = std::move(*JB); 604cb7995a1SStefan Gränitz } 605cb7995a1SStefan Gränitz 60692f9852fSVassil Vassilev llvm::Error Err = llvm::Error::success(); 6079a9546e3SVassil Vassilev #ifdef __EMSCRIPTEN__ 6089a9546e3SVassil Vassilev auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx); 6099a9546e3SVassil Vassilev #else 610cb7995a1SStefan Gränitz auto Executor = 611cb7995a1SStefan Gränitz std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err); 6129a9546e3SVassil Vassilev #endif 613d978730dSAnubhab Ghosh if (!Err) 614d978730dSAnubhab Ghosh IncrExecutor = std::move(Executor); 61549f95321SVassil Vassilev 616d978730dSAnubhab Ghosh return Err; 617d978730dSAnubhab Ghosh } 618d978730dSAnubhab Ghosh 619bde7a6b7SStefan Gränitz void Interpreter::ResetExecutor() { IncrExecutor.reset(); } 620bde7a6b7SStefan Gränitz 621d978730dSAnubhab Ghosh llvm::Error Interpreter::Execute(PartialTranslationUnit &T) { 622d978730dSAnubhab Ghosh assert(T.TheModule); 623a8744066SVassil Vassilev LLVM_DEBUG(llvm::dbgs() 624a8744066SVassil Vassilev << "execute-ptu " 625a8744066SVassil Vassilev << ((std::find(PTUs.begin(), PTUs.end(), T) != PTUs.end()) 626a8744066SVassil Vassilev ? std::distance(PTUs.begin(), 627a8744066SVassil Vassilev std::find(PTUs.begin(), PTUs.end(), T)) 628a8744066SVassil Vassilev : -1) 629a8744066SVassil Vassilev << ": [TU=" << T.TUPart << ", M=" << T.TheModule.get() << " (" 630a8744066SVassil Vassilev << T.TheModule->getName() << ")]\n"); 631d978730dSAnubhab Ghosh if (!IncrExecutor) { 632d978730dSAnubhab Ghosh auto Err = CreateExecutor(); 63392f9852fSVassil Vassilev if (Err) 63492f9852fSVassil Vassilev return Err; 63592f9852fSVassil Vassilev } 63692f9852fSVassil Vassilev // FIXME: Add a callback to retain the llvm::Module once the JIT is done. 637dea5a9ccSJun Zhang if (auto Err = IncrExecutor->addModule(T)) 63892f9852fSVassil Vassilev return Err; 63992f9852fSVassil Vassilev 64092f9852fSVassil Vassilev if (auto Err = IncrExecutor->runCtors()) 64192f9852fSVassil Vassilev return Err; 64292f9852fSVassil Vassilev 64392f9852fSVassil Vassilev return llvm::Error::success(); 64492f9852fSVassil Vassilev } 645c24a5808SVassil Vassilev 6465111286fSJun Zhang llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) { 6475111286fSJun Zhang 6485111286fSJun Zhang auto PTU = Parse(Code); 6495111286fSJun Zhang if (!PTU) 6505111286fSJun Zhang return PTU.takeError(); 6515111286fSJun Zhang if (PTU->TheModule) 6525111286fSJun Zhang if (llvm::Error Err = Execute(*PTU)) 6535111286fSJun Zhang return Err; 6545111286fSJun Zhang 6555111286fSJun Zhang if (LastValue.isValid()) { 6565111286fSJun Zhang if (!V) { 6575111286fSJun Zhang LastValue.dump(); 6585111286fSJun Zhang LastValue.clear(); 6595111286fSJun Zhang } else 6605111286fSJun Zhang *V = std::move(LastValue); 6615111286fSJun Zhang } 6625111286fSJun Zhang return llvm::Error::success(); 6635111286fSJun Zhang } 6645111286fSJun Zhang 665fe1f3445SJun Zhang llvm::Expected<llvm::orc::ExecutorAddr> 6664fb0805cSVassil Vassilev Interpreter::getSymbolAddress(GlobalDecl GD) const { 6674fb0805cSVassil Vassilev if (!IncrExecutor) 6684fb0805cSVassil Vassilev return llvm::make_error<llvm::StringError>("Operation failed. " 6694fb0805cSVassil Vassilev "No execution engine", 6704fb0805cSVassil Vassilev std::error_code()); 671a72d7eeaSVassil Vassilev llvm::StringRef MangledName = getCodeGen()->GetMangledName(GD); 6724fb0805cSVassil Vassilev return getSymbolAddress(MangledName); 6734fb0805cSVassil Vassilev } 6744fb0805cSVassil Vassilev 675fe1f3445SJun Zhang llvm::Expected<llvm::orc::ExecutorAddr> 6764fb0805cSVassil Vassilev Interpreter::getSymbolAddress(llvm::StringRef IRName) const { 677c24a5808SVassil Vassilev if (!IncrExecutor) 678c24a5808SVassil Vassilev return llvm::make_error<llvm::StringError>("Operation failed. " 679c24a5808SVassil Vassilev "No execution engine", 680c24a5808SVassil Vassilev std::error_code()); 681c24a5808SVassil Vassilev 6824fb0805cSVassil Vassilev return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName); 6834fb0805cSVassil Vassilev } 6844fb0805cSVassil Vassilev 685fe1f3445SJun Zhang llvm::Expected<llvm::orc::ExecutorAddr> 6864fb0805cSVassil Vassilev Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const { 6874fb0805cSVassil Vassilev if (!IncrExecutor) 6884fb0805cSVassil Vassilev return llvm::make_error<llvm::StringError>("Operation failed. " 6894fb0805cSVassil Vassilev "No execution engine", 6904fb0805cSVassil Vassilev std::error_code()); 6914fb0805cSVassil Vassilev 6924fb0805cSVassil Vassilev return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName); 693c24a5808SVassil Vassilev } 694dea5a9ccSJun Zhang 695dea5a9ccSJun Zhang llvm::Error Interpreter::Undo(unsigned N) { 696dea5a9ccSJun Zhang 6975111286fSJun Zhang if (N > getEffectivePTUSize()) 698dea5a9ccSJun Zhang return llvm::make_error<llvm::StringError>("Operation failed. " 699dea5a9ccSJun Zhang "Too many undos", 700dea5a9ccSJun Zhang std::error_code()); 701dea5a9ccSJun Zhang for (unsigned I = 0; I < N; I++) { 702dea5a9ccSJun Zhang if (IncrExecutor) { 703dea5a9ccSJun Zhang if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back())) 704dea5a9ccSJun Zhang return Err; 705dea5a9ccSJun Zhang } 706dea5a9ccSJun Zhang 707a72d7eeaSVassil Vassilev IncrParser->CleanUpPTU(PTUs.back().TUPart); 708dea5a9ccSJun Zhang PTUs.pop_back(); 709dea5a9ccSJun Zhang } 710dea5a9ccSJun Zhang return llvm::Error::success(); 711dea5a9ccSJun Zhang } 712d978730dSAnubhab Ghosh 713d978730dSAnubhab Ghosh llvm::Error Interpreter::LoadDynamicLibrary(const char *name) { 714d978730dSAnubhab Ghosh auto EE = getExecutionEngine(); 715d978730dSAnubhab Ghosh if (!EE) 716d978730dSAnubhab Ghosh return EE.takeError(); 717d978730dSAnubhab Ghosh 718ebb35088SSahilPatidar auto &DL = EE->getDataLayout(); 719ebb35088SSahilPatidar 720ebb35088SSahilPatidar if (auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load( 721ebb35088SSahilPatidar name, DL.getGlobalPrefix())) 722*61ab36a3SDavide Italiano EE->getMainJITDylib().addGenerator(std::move(*DLSG)); 723d978730dSAnubhab Ghosh else 724d978730dSAnubhab Ghosh return DLSG.takeError(); 725d978730dSAnubhab Ghosh 726d978730dSAnubhab Ghosh return llvm::Error::success(); 727d978730dSAnubhab Ghosh } 7285111286fSJun Zhang 729a72d7eeaSVassil Vassilev std::unique_ptr<llvm::Module> Interpreter::GenModule() { 730a72d7eeaSVassil Vassilev static unsigned ID = 0; 731a72d7eeaSVassil Vassilev if (CodeGenerator *CG = getCodeGen()) { 732a72d7eeaSVassil Vassilev // Clang's CodeGen is designed to work with a single llvm::Module. In many 733a72d7eeaSVassil Vassilev // cases for convenience various CodeGen parts have a reference to the 734a72d7eeaSVassil Vassilev // llvm::Module (TheModule or Module) which does not change when a new 735a72d7eeaSVassil Vassilev // module is pushed. However, the execution engine wants to take ownership 736a72d7eeaSVassil Vassilev // of the module which does not map well to CodeGen's design. To work this 737a72d7eeaSVassil Vassilev // around we created an empty module to make CodeGen happy. We should make 738a72d7eeaSVassil Vassilev // sure it always stays empty. 739a8744066SVassil Vassilev assert(((!CachedInCodeGenModule || 740a8744066SVassil Vassilev !getCompilerInstance()->getPreprocessorOpts().Includes.empty()) || 741a8744066SVassil Vassilev (CachedInCodeGenModule->empty() && 742a72d7eeaSVassil Vassilev CachedInCodeGenModule->global_empty() && 743a72d7eeaSVassil Vassilev CachedInCodeGenModule->alias_empty() && 744a72d7eeaSVassil Vassilev CachedInCodeGenModule->ifunc_empty())) && 745a72d7eeaSVassil Vassilev "CodeGen wrote to a readonly module"); 746a72d7eeaSVassil Vassilev std::unique_ptr<llvm::Module> M(CG->ReleaseModule()); 747a72d7eeaSVassil Vassilev CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext()); 748a72d7eeaSVassil Vassilev return M; 7495111286fSJun Zhang } 750ec2875ceSStefan Gränitz return nullptr; 7517091dfc0SVassil Vassilev } 752ec2875ceSStefan Gränitz 753a72d7eeaSVassil Vassilev CodeGenerator *Interpreter::getCodeGen() const { 754a72d7eeaSVassil Vassilev FrontendAction *WrappedAct = Act->getWrapped(); 755a72d7eeaSVassil Vassilev if (!WrappedAct->hasIRSupport()) 756a72d7eeaSVassil Vassilev return nullptr; 757a72d7eeaSVassil Vassilev return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator(); 7585111286fSJun Zhang } 759a72d7eeaSVassil Vassilev } // namespace clang 760