brintos

brintos / llvm-project-archived public Read only

0
0
Text · 28.7 KiB · 6cbc5e9 Raw
819 lines · cpp
1//===------ Interpreter.cpp - Incremental Compilation and Execution -------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the component which performs incremental code10// compilation and execution.11//12//===----------------------------------------------------------------------===//13 14#include "DeviceOffload.h"15#include "IncrementalAction.h"16#include "IncrementalExecutor.h"17#include "IncrementalParser.h"18#include "InterpreterUtils.h"19#include "llvm/Support/VirtualFileSystem.h"20#ifdef __EMSCRIPTEN__21#include "Wasm.h"22#include <dlfcn.h>23#endif // __EMSCRIPTEN__24 25#include "clang/AST/ASTConsumer.h"26#include "clang/AST/ASTContext.h"27#include "clang/AST/Mangle.h"28#include "clang/AST/TypeVisitor.h"29#include "clang/Basic/DiagnosticSema.h"30#include "clang/Basic/TargetInfo.h"31#include "clang/CodeGen/CodeGenAction.h"32#include "clang/CodeGen/ObjectFilePCHContainerWriter.h"33#include "clang/Driver/Compilation.h"34#include "clang/Driver/Driver.h"35#include "clang/Driver/Job.h"36#include "clang/Driver/Tool.h"37#include "clang/Frontend/CompilerInstance.h"38#include "clang/Frontend/FrontendAction.h"39#include "clang/Frontend/MultiplexConsumer.h"40#include "clang/Frontend/TextDiagnosticBuffer.h"41#include "clang/FrontendTool/Utils.h"42#include "clang/Interpreter/Interpreter.h"43#include "clang/Interpreter/Value.h"44#include "clang/Lex/PreprocessorOptions.h"45#include "clang/Options/OptionUtils.h"46#include "clang/Options/Options.h"47#include "clang/Sema/Lookup.h"48#include "clang/Serialization/ObjectFilePCHContainerReader.h"49#include "llvm/ExecutionEngine/JITSymbol.h"50#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"51#include "llvm/ExecutionEngine/Orc/LLJIT.h"52#include "llvm/IR/Module.h"53#include "llvm/Support/Errc.h"54#include "llvm/Support/ErrorHandling.h"55#include "llvm/Support/raw_ostream.h"56#include "llvm/TargetParser/Host.h"57#include "llvm/Transforms/Utils/Cloning.h" // for CloneModule58 59#define DEBUG_TYPE "clang-repl"60 61using namespace clang;62// FIXME: Figure out how to unify with namespace init_convenience from63//        tools/clang-import-test/clang-import-test.cpp64namespace {65/// Retrieves the clang CC1 specific flags out of the compilation's jobs.66/// \returns NULL on error.67static llvm::Expected<const llvm::opt::ArgStringList *>68GetCC1Arguments(DiagnosticsEngine *Diagnostics,69                driver::Compilation *Compilation) {70  // We expect to get back exactly one Command job, if we didn't something71  // failed. Extract that job from the Compilation.72  const driver::JobList &Jobs = Compilation->getJobs();73  if (!Jobs.size() || !isa<driver::Command>(*Jobs.begin()))74    return llvm::createStringError(llvm::errc::not_supported,75                                   "Driver initialization failed. "76                                   "Unable to create a driver job");77 78  // The one job we find should be to invoke clang again.79  const driver::Command *Cmd = cast<driver::Command>(&(*Jobs.begin()));80  if (llvm::StringRef(Cmd->getCreator().getName()) != "clang")81    return llvm::createStringError(llvm::errc::not_supported,82                                   "Driver initialization failed");83 84  return &Cmd->getArguments();85}86 87static llvm::Expected<std::unique_ptr<CompilerInstance>>88CreateCI(const llvm::opt::ArgStringList &Argv) {89  std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());90 91  // Register the support for object-file-wrapped Clang modules.92  // FIXME: Clang should register these container operations automatically.93  auto PCHOps = Clang->getPCHContainerOperations();94  PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());95  PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());96 97  // Buffer diagnostics from argument parsing so that we can output them using98  // a well formed diagnostic object.99  DiagnosticOptions DiagOpts;100  TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;101  DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DiagsBuffer);102  bool Success = CompilerInvocation::CreateFromArgs(103      Clang->getInvocation(), llvm::ArrayRef(Argv.begin(), Argv.size()), Diags);104 105  // Infer the builtin include path if unspecified.106  if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&107      Clang->getHeaderSearchOpts().ResourceDir.empty())108    Clang->getHeaderSearchOpts().ResourceDir =109        GetResourcesPath(Argv[0], nullptr);110 111  Clang->createVirtualFileSystem();112 113  // Create the actual diagnostics engine.114  Clang->createDiagnostics();115  if (!Clang->hasDiagnostics())116    return llvm::createStringError(llvm::errc::not_supported,117                                   "Initialization failed. "118                                   "Unable to create diagnostics engine");119 120  DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());121  if (!Success)122    return llvm::createStringError(llvm::errc::not_supported,123                                   "Initialization failed. "124                                   "Unable to flush diagnostics");125 126  // FIXME: Merge with CompilerInstance::ExecuteAction.127  llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release();128  Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB);129 130  Clang->setTarget(TargetInfo::CreateTargetInfo(131      Clang->getDiagnostics(), Clang->getInvocation().getTargetOpts()));132  if (!Clang->hasTarget())133    return llvm::createStringError(llvm::errc::not_supported,134                                   "Initialization failed. "135                                   "Target is missing");136 137  Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts(),138                            Clang->getAuxTarget());139 140  // Don't clear the AST before backend codegen since we do codegen multiple141  // times, reusing the same AST.142  Clang->getCodeGenOpts().ClearASTBeforeBackend = false;143 144  Clang->getFrontendOpts().DisableFree = false;145  Clang->getCodeGenOpts().DisableFree = false;146  return std::move(Clang);147}148 149} // anonymous namespace150 151namespace clang {152 153llvm::Expected<std::unique_ptr<CompilerInstance>>154IncrementalCompilerBuilder::create(std::string TT,155                                   std::vector<const char *> &ClangArgv) {156 157  // If we don't know ClangArgv0 or the address of main() at this point, try158  // to guess it anyway (it's possible on some platforms).159  std::string MainExecutableName =160      llvm::sys::fs::getMainExecutable(nullptr, nullptr);161 162  ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());163 164  // Prepending -c to force the driver to do something if no action was165  // specified. By prepending we allow users to override the default166  // action and use other actions in incremental mode.167  // FIXME: Print proper driver diagnostics if the driver flags are wrong.168  // We do C++ by default; append right after argv[0] if no "-x" given169  ClangArgv.insert(ClangArgv.end(), "-Xclang");170  ClangArgv.insert(ClangArgv.end(), "-fincremental-extensions");171  ClangArgv.insert(ClangArgv.end(), "-c");172 173  // Put a dummy C++ file on to ensure there's at least one compile job for the174  // driver to construct.175  ClangArgv.push_back("<<< inputs >>>");176 177  // Buffer diagnostics from argument parsing so that we can output them using a178  // well formed diagnostic object.179  std::unique_ptr<DiagnosticOptions> DiagOpts =180      CreateAndPopulateDiagOpts(ClangArgv);181  TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;182  DiagnosticsEngine Diags(DiagnosticIDs::create(), *DiagOpts, DiagsBuffer);183 184  driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags);185  Driver.setCheckInputsExist(false); // the input comes from mem buffers186  llvm::ArrayRef<const char *> RF = llvm::ArrayRef(ClangArgv);187  std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF));188 189  if (Compilation->getArgs().hasArg(options::OPT_v))190    Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false);191 192  auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());193  if (auto Err = ErrOrCC1Args.takeError())194    return std::move(Err);195 196  return CreateCI(**ErrOrCC1Args);197}198 199llvm::Expected<std::unique_ptr<CompilerInstance>>200IncrementalCompilerBuilder::CreateCpp() {201  std::vector<const char *> Argv;202  Argv.reserve(5 + 1 + UserArgs.size());203  Argv.push_back("-xc++");204#ifdef __EMSCRIPTEN__205  Argv.push_back("-target");206  Argv.push_back("wasm32-unknown-emscripten");207  Argv.push_back("-fvisibility=default");208#endif209  llvm::append_range(Argv, UserArgs);210 211  std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();212  return IncrementalCompilerBuilder::create(TT, Argv);213}214 215llvm::Expected<std::unique_ptr<CompilerInstance>>216IncrementalCompilerBuilder::createCuda(bool device) {217  std::vector<const char *> Argv;218  Argv.reserve(5 + 4 + UserArgs.size());219 220  Argv.push_back("-xcuda");221  if (device)222    Argv.push_back("--cuda-device-only");223  else224    Argv.push_back("--cuda-host-only");225 226  std::string SDKPathArg = "--cuda-path=";227  if (!CudaSDKPath.empty()) {228    SDKPathArg += CudaSDKPath;229    Argv.push_back(SDKPathArg.c_str());230  }231 232  std::string ArchArg = "--offload-arch=";233  if (!OffloadArch.empty()) {234    ArchArg += OffloadArch;235    Argv.push_back(ArchArg.c_str());236  }237 238  llvm::append_range(Argv, UserArgs);239 240  std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();241  return IncrementalCompilerBuilder::create(TT, Argv);242}243 244llvm::Expected<std::unique_ptr<CompilerInstance>>245IncrementalCompilerBuilder::CreateCudaDevice() {246  return IncrementalCompilerBuilder::createCuda(true);247}248 249llvm::Expected<std::unique_ptr<CompilerInstance>>250IncrementalCompilerBuilder::CreateCudaHost() {251  return IncrementalCompilerBuilder::createCuda(false);252}253 254Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,255                         llvm::Error &ErrOut,256                         std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder,257                         std::unique_ptr<clang::ASTConsumer> Consumer,258                         JITConfig Config)259    : JITBuilder(std::move(JITBuilder)) {260  CI = std::move(Instance);261  llvm::ErrorAsOutParameter EAO(&ErrOut);262  auto LLVMCtx = std::make_unique<llvm::LLVMContext>();263  TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));264 265  Act = TSCtx->withContextDo([&](llvm::LLVMContext *Ctx) {266    return std::make_unique<IncrementalAction>(*CI, *Ctx, ErrOut, *this,267                                               std::move(Consumer));268  });269 270  if (ErrOut)271    return;272  CI->ExecuteAction(*Act);273 274  IncrParser =275      std::make_unique<IncrementalParser>(*CI, Act.get(), ErrOut, PTUs);276 277  if (ErrOut)278    return;279 280  if (Act->getCodeGen()) {281    Act->CacheCodeGenModule();282    // The initial PTU is filled by `-include`/`-include-pch` or by CUDA283    // includes automatically.284    if (!CI->getPreprocessorOpts().Includes.empty() ||285        !CI->getPreprocessorOpts().ImplicitPCHInclude.empty()) {286      // We can't really directly pass the CachedInCodeGenModule to the Jit287      // because it will steal it, causing dangling references as explained in288      // Interpreter::Execute289      auto M = llvm::CloneModule(*Act->getCachedCodeGenModule());290      ASTContext &C = CI->getASTContext();291      IncrParser->RegisterPTU(C.getTranslationUnitDecl(), std::move(M));292    }293    if (llvm::Error Err = CreateExecutor(Config)) {294      ErrOut = joinErrors(std::move(ErrOut), std::move(Err));295      return;296    }297  }298 299  // Not all frontends support code-generation, e.g. ast-dump actions don't300  if (Act->getCodeGen()) {301    // Process the PTUs that came from initialization. For example -include will302    // give us a header that's processed at initialization of the preprocessor.303    for (PartialTranslationUnit &PTU : PTUs)304      if (llvm::Error Err = Execute(PTU)) {305        ErrOut = joinErrors(std::move(ErrOut), std::move(Err));306        return;307      }308  }309}310 311Interpreter::~Interpreter() {312  IncrParser.reset();313  Act->FinalizeAction();314  if (DeviceParser)315    DeviceParser.reset();316  if (DeviceAct)317    DeviceAct->FinalizeAction();318  if (IncrExecutor) {319    if (llvm::Error Err = IncrExecutor->cleanUp())320      llvm::report_fatal_error(321          llvm::Twine("Failed to clean up IncrementalExecutor: ") +322          toString(std::move(Err)));323  }324}325 326// These better to put in a runtime header but we can't. This is because we327// can't find the precise resource directory in unittests so we have to hard328// code them.329const char *const Runtimes = R"(330    #define __CLANG_REPL__ 1331#ifdef __cplusplus332    #define EXTERN_C extern "C"333    struct __clang_Interpreter_NewTag{} __ci_newtag;334    void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept;335    template <class T, class = T (*)() /*disable for arrays*/>336    void __clang_Interpreter_SetValueCopyArr(const T* Src, void* Placement, unsigned long Size) {337      for (auto Idx = 0; Idx < Size; ++Idx)338        new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]);339    }340    template <class T, unsigned long N>341    void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {342      __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);343    }344#else345    #define EXTERN_C extern346    EXTERN_C void *memcpy(void *restrict dst, const void *restrict src, __SIZE_TYPE__ n);347    EXTERN_C inline void __clang_Interpreter_SetValueCopyArr(const void* Src, void* Placement, unsigned long Size) {348      memcpy(Placement, Src, Size);349    }350#endif // __cplusplus351  EXTERN_C void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);352  EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...);353)";354 355llvm::Expected<std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, uint32_t>>356Interpreter::outOfProcessJITBuilder(JITConfig Config) {357  std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;358  uint32_t childPid = -1;359  if (!Config.OOPExecutor.empty()) {360    // Launch an out-of-process executor locally in a child process.361    auto ResultOrErr = IncrementalExecutor::launchExecutor(362        Config.OOPExecutor, Config.UseSharedMemory, Config.SlabAllocateSize,363        Config.CustomizeFork);364    if (!ResultOrErr)365      return ResultOrErr.takeError();366    childPid = ResultOrErr->second;367    auto EPCOrErr = std::move(ResultOrErr->first);368    EPC = std::move(EPCOrErr);369  } else if (Config.OOPExecutorConnect != "") {370#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS371    auto EPCOrErr = IncrementalExecutor::connectTCPSocket(372        Config.OOPExecutorConnect, Config.UseSharedMemory,373        Config.SlabAllocateSize);374    if (!EPCOrErr)375      return EPCOrErr.takeError();376    EPC = std::move(*EPCOrErr);377#else378    return llvm::make_error<llvm::StringError>(379        "Out-of-process JIT over TCP is not supported on this platform",380        std::error_code());381#endif382  }383 384  std::unique_ptr<llvm::orc::LLJITBuilder> JB;385  if (EPC) {386    auto JBOrErr = clang::Interpreter::createLLJITBuilder(387        std::move(EPC), Config.OrcRuntimePath);388    if (!JBOrErr)389      return JBOrErr.takeError();390    JB = std::move(*JBOrErr);391  }392 393  return std::make_pair(std::move(JB), childPid);394}395 396llvm::Expected<std::string>397Interpreter::getOrcRuntimePath(const driver::ToolChain &TC) {398  const std::array<const char *, 3> OrcRTLibNames = {399      "liborc_rt.a", "liborc_rt_osx.a", "liborc_rt-x86_64.a"};400 401  auto findInDir = [&](llvm::StringRef Base) -> std::optional<std::string> {402    for (const char *LibName : OrcRTLibNames) {403      llvm::SmallString<256> CandidatePath(Base);404      llvm::sys::path::append(CandidatePath, LibName);405      if (llvm::sys::fs::exists(CandidatePath))406        return std::string(CandidatePath.str());407    }408    return std::nullopt;409  };410 411  std::string SearchedPaths;412 413  if (std::optional<std::string> CompilerRTPath = TC.getCompilerRTPath()) {414    if (auto Found = findInDir(*CompilerRTPath))415      return *Found;416    SearchedPaths += *CompilerRTPath;417  } else {418    return llvm::make_error<llvm::StringError>("CompilerRT path not found",419                                               std::error_code());420  }421 422  if (std::optional<std::string> ResourceDir = TC.getRuntimePath()) {423    if (auto Found = findInDir(*ResourceDir))424      return *Found;425    if (!SearchedPaths.empty())426      SearchedPaths += "; ";427    SearchedPaths += *ResourceDir;428  } else {429    return llvm::make_error<llvm::StringError>("ResourceDir path not found",430                                               std::error_code());431  }432 433  return llvm::make_error<llvm::StringError>(434      llvm::Twine("OrcRuntime library not found in: ") + SearchedPaths,435      std::error_code());436}437 438llvm::Expected<std::unique_ptr<Interpreter>>439Interpreter::create(std::unique_ptr<CompilerInstance> CI, JITConfig Config) {440 441  if (Config.IsOutOfProcess) {442    const TargetInfo &TI = CI->getTarget();443    const llvm::Triple &Triple = TI.getTriple();444 445    DiagnosticsEngine &Diags = CI->getDiagnostics();446    std::string BinaryName = llvm::sys::fs::getMainExecutable(nullptr, nullptr);447    driver::Driver Driver(BinaryName, Triple.str(), Diags);448    // Need fake args to get the driver to create a compilation.449    std::vector<const char *> Args = {"clang", "--version"};450    std::unique_ptr<clang::driver::Compilation> C(451        Driver.BuildCompilation(Args));452    if (!C) {453      return llvm::make_error<llvm::StringError>(454          "Failed to create driver compilation for out-of-process JIT",455          std::error_code());456    }457    if (Config.OrcRuntimePath == "") {458      const clang::driver::ToolChain &TC = C->getDefaultToolChain();459 460      auto OrcRuntimePathOrErr = getOrcRuntimePath(TC);461      if (!OrcRuntimePathOrErr) {462        return OrcRuntimePathOrErr.takeError();463      }464 465      Config.OrcRuntimePath = *OrcRuntimePathOrErr;466    }467  }468 469  llvm::Error Err = llvm::Error::success();470  std::unique_ptr<llvm::orc::LLJITBuilder> JB;471 472  auto Interp = std::unique_ptr<Interpreter>(new Interpreter(473      std::move(CI), Err, std::move(JB), /*Consumer=*/nullptr, Config));474  if (auto E = std::move(Err))475    return std::move(E);476 477  // Add runtime code and set a marker to hide it from user code. Undo will not478  // go through that.479  if (auto E = Interp->ParseAndExecute(Runtimes))480    return std::move(E);481 482  Interp->markUserCodeStart();483 484  return std::move(Interp);485}486 487llvm::Expected<std::unique_ptr<Interpreter>>488Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,489                            std::unique_ptr<CompilerInstance> DCI) {490  // avoid writing fat binary to disk using an in-memory virtual file system491  llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> IMVFS =492      std::make_unique<llvm::vfs::InMemoryFileSystem>();493  llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS =494      std::make_unique<llvm::vfs::OverlayFileSystem>(495          llvm::vfs::getRealFileSystem());496  OverlayVFS->pushOverlay(IMVFS);497  CI->createVirtualFileSystem(OverlayVFS);498  CI->createFileManager();499 500  llvm::Expected<std::unique_ptr<Interpreter>> InterpOrErr =501      Interpreter::create(std::move(CI));502  if (!InterpOrErr)503    return InterpOrErr;504 505  std::unique_ptr<Interpreter> Interp = std::move(*InterpOrErr);506 507  llvm::Error Err = llvm::Error::success();508 509  auto DeviceAct = Interp->TSCtx->withContextDo([&](llvm::LLVMContext *Ctx) {510    return std::make_unique<IncrementalAction>(*DCI, *Ctx, Err, *Interp);511  });512 513  if (Err)514    return std::move(Err);515 516  Interp->DeviceAct = std::move(DeviceAct);517 518  DCI->ExecuteAction(*Interp->DeviceAct);519 520  Interp->DeviceCI = std::move(DCI);521 522  auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(523      *Interp->DeviceCI, *Interp->getCompilerInstance(),524      Interp->DeviceAct.get(), IMVFS, Err, Interp->PTUs);525 526  if (Err)527    return std::move(Err);528 529  Interp->DeviceParser = std::move(DeviceParser);530  return std::move(Interp);531}532 533CompilerInstance *Interpreter::getCompilerInstance() { return CI.get(); }534const CompilerInstance *Interpreter::getCompilerInstance() const {535  return const_cast<Interpreter *>(this)->getCompilerInstance();536}537 538llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() {539  if (!IncrExecutor) {540    if (auto Err = CreateExecutor())541      return std::move(Err);542  }543 544  return IncrExecutor->GetExecutionEngine();545}546 547ASTContext &Interpreter::getASTContext() {548  return getCompilerInstance()->getASTContext();549}550 551const ASTContext &Interpreter::getASTContext() const {552  return getCompilerInstance()->getASTContext();553}554 555void Interpreter::markUserCodeStart() {556  assert(!InitPTUSize && "We only do this once");557  InitPTUSize = PTUs.size();558}559 560size_t Interpreter::getEffectivePTUSize() const {561  assert(PTUs.size() >= InitPTUSize && "empty PTU list?");562  return PTUs.size() - InitPTUSize;563}564 565uint32_t Interpreter::getOutOfProcessExecutorPID() const {566  if (IncrExecutor)567    return IncrExecutor->getOutOfProcessChildPid();568  return -1;569}570 571llvm::Expected<PartialTranslationUnit &>572Interpreter::Parse(llvm::StringRef Code) {573  // If we have a device parser, parse it first. The generated code will be574  // included in the host compilation575  if (DeviceParser) {576    llvm::Expected<TranslationUnitDecl *> DeviceTU = DeviceParser->Parse(Code);577    if (auto E = DeviceTU.takeError())578      return std::move(E);579 580    DeviceParser->RegisterPTU(*DeviceTU);581 582    llvm::Expected<llvm::StringRef> PTX = DeviceParser->GeneratePTX();583    if (!PTX)584      return PTX.takeError();585 586    llvm::Error Err = DeviceParser->GenerateFatbinary();587    if (Err)588      return std::move(Err);589  }590 591  // Tell the interpreter sliently ignore unused expressions since value592  // printing could cause it.593  getCompilerInstance()->getDiagnostics().setSeverity(594      clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation());595 596  llvm::Expected<TranslationUnitDecl *> TuOrErr = IncrParser->Parse(Code);597  if (!TuOrErr)598    return TuOrErr.takeError();599 600  PartialTranslationUnit &LastPTU = IncrParser->RegisterPTU(*TuOrErr);601 602  return LastPTU;603}604 605static llvm::Expected<llvm::orc::JITTargetMachineBuilder>606createJITTargetMachineBuilder(const std::string &TT) {607  if (TT == llvm::sys::getProcessTriple())608    // This fails immediately if the target backend is not registered609    return llvm::orc::JITTargetMachineBuilder::detectHost();610 611  // If the target backend is not registered, LLJITBuilder::create() will fail612  return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT));613}614 615llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>616Interpreter::createLLJITBuilder(617    std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC,618    llvm::StringRef OrcRuntimePath) {619  const std::string &TT = EPC->getTargetTriple().getTriple();620  auto JTMB = createJITTargetMachineBuilder(TT);621  if (!JTMB)622    return JTMB.takeError();623  auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB));624  if (!JB)625    return JB.takeError();626 627  (*JB)->setExecutorProcessControl(std::move(EPC));628  (*JB)->setPlatformSetUp(629      llvm::orc::ExecutorNativePlatform(OrcRuntimePath.str()));630 631  return std::move(*JB);632}633 634llvm::Error Interpreter::CreateExecutor(JITConfig Config) {635  if (IncrExecutor)636    return llvm::make_error<llvm::StringError>("Operation failed. "637                                               "Execution engine exists",638                                               std::error_code());639  if (!Act->getCodeGen())640    return llvm::make_error<llvm::StringError>("Operation failed. "641                                               "No code generator available",642                                               std::error_code());643 644  const std::string &TT = getCompilerInstance()->getTargetOpts().Triple;645  llvm::Triple TargetTriple(TT);646  bool IsWindowsTarget = TargetTriple.isOSWindows();647 648  if (!IsWindowsTarget && Config.IsOutOfProcess) {649    if (!JITBuilder) {650      auto ResOrErr = outOfProcessJITBuilder(Config);651      if (!ResOrErr)652        return ResOrErr.takeError();653      JITBuilder = std::move(ResOrErr->first);654      Config.ExecutorPID = ResOrErr->second;655    }656    if (!JITBuilder)657      return llvm::make_error<llvm::StringError>(658          "Operation failed. No LLJITBuilder for out-of-process JIT",659          std::error_code());660  }661 662  if (!JITBuilder) {663    auto JTMB = createJITTargetMachineBuilder(TT);664    if (!JTMB)665      return JTMB.takeError();666    if (Config.CM)667      JTMB->setCodeModel(Config.CM);668    auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB));669    if (!JB)670      return JB.takeError();671    JITBuilder = std::move(*JB);672  }673 674  llvm::Error Err = llvm::Error::success();675 676  // Fix: Declare Executor as the appropriate unique_ptr type677  std::unique_ptr<IncrementalExecutor> Executor;678 679#ifdef __EMSCRIPTEN__680  Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);681#else682  Executor =683      std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Config, Err);684#endif685  if (!Err)686    IncrExecutor = std::move(Executor);687 688  return Err;689}690 691void Interpreter::ResetExecutor() { IncrExecutor.reset(); }692 693llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {694  assert(T.TheModule);695  LLVM_DEBUG(696      llvm::dbgs() << "execute-ptu "697                   << (llvm::is_contained(PTUs, T)698                           ? std::distance(PTUs.begin(), llvm::find(PTUs, T))699                           : -1)700                   << ": [TU=" << T.TUPart << ", M=" << T.TheModule.get()701                   << " (" << T.TheModule->getName() << ")]\n");702  if (!IncrExecutor) {703    auto Err = CreateExecutor();704    if (Err)705      return Err;706  }707  // FIXME: Add a callback to retain the llvm::Module once the JIT is done.708  if (auto Err = IncrExecutor->addModule(T))709    return Err;710 711  if (auto Err = IncrExecutor->runCtors())712    return Err;713 714  return llvm::Error::success();715}716 717llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {718 719  auto PTU = Parse(Code);720  if (!PTU)721    return PTU.takeError();722  if (PTU->TheModule)723    if (llvm::Error Err = Execute(*PTU))724      return Err;725 726  if (LastValue.isValid()) {727    if (!V) {728      LastValue.dump();729      LastValue.clear();730    } else731      *V = std::move(LastValue);732  }733  return llvm::Error::success();734}735 736llvm::Expected<llvm::orc::ExecutorAddr>737Interpreter::getSymbolAddress(GlobalDecl GD) const {738  if (!IncrExecutor)739    return llvm::make_error<llvm::StringError>("Operation failed. "740                                               "No execution engine",741                                               std::error_code());742  llvm::StringRef MangledName = Act->getCodeGen()->GetMangledName(GD);743  return getSymbolAddress(MangledName);744}745 746llvm::Expected<llvm::orc::ExecutorAddr>747Interpreter::getSymbolAddress(llvm::StringRef IRName) const {748  if (!IncrExecutor)749    return llvm::make_error<llvm::StringError>("Operation failed. "750                                               "No execution engine",751                                               std::error_code());752 753  return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName);754}755 756llvm::Expected<llvm::orc::ExecutorAddr>757Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const {758  if (!IncrExecutor)759    return llvm::make_error<llvm::StringError>("Operation failed. "760                                               "No execution engine",761                                               std::error_code());762 763  return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName);764}765 766llvm::Error Interpreter::Undo(unsigned N) {767 768  if (getEffectivePTUSize() == 0) {769    return llvm::make_error<llvm::StringError>("Operation failed. "770                                               "No input left to undo",771                                               std::error_code());772  } else if (N > getEffectivePTUSize()) {773    return llvm::make_error<llvm::StringError>(774        llvm::formatv(775            "Operation failed. Wanted to undo {0} inputs, only have {1}.", N,776            getEffectivePTUSize()),777        std::error_code());778  }779 780  for (unsigned I = 0; I < N; I++) {781    if (IncrExecutor) {782      if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back()))783        return Err;784    }785 786    IncrParser->CleanUpPTU(PTUs.back().TUPart);787    PTUs.pop_back();788  }789  return llvm::Error::success();790}791 792llvm::Error Interpreter::LoadDynamicLibrary(const char *name) {793#ifdef __EMSCRIPTEN__794  void *handle = dlopen(name, RTLD_NOW | RTLD_GLOBAL);795  if (!handle) {796    llvm::errs() << dlerror() << '\n';797    return llvm::make_error<llvm::StringError>("Failed to load dynamic library",798                                               llvm::inconvertibleErrorCode());799  }800#else801  auto EE = getExecutionEngine();802  if (!EE)803    return EE.takeError();804 805  if (llvm::Expected<806          std::unique_ptr<llvm::orc::EPCDynamicLibrarySearchGenerator>>807          DLSG = llvm::orc::EPCDynamicLibrarySearchGenerator::Load(808              EE->getExecutionSession(), name))809    // FIXME: Eventually we should put each library in its own JITDylib and810    //        turn off process symbols by default.811    EE->getProcessSymbolsJITDylib()->addGenerator(std::move(*DLSG));812  else813    return DLSG.takeError();814#endif815 816  return llvm::Error::success();817}818} // end namespace clang819