Index: clang/include/clang/Interpreter/Interpreter.h =================================================================== --- clang/include/clang/Interpreter/Interpreter.h +++ clang/include/clang/Interpreter/Interpreter.h @@ -49,13 +49,18 @@ std::unique_ptr TSCtx; std::unique_ptr IncrParser; std::unique_ptr IncrExecutor; + std::string OrcRuntimePath; - Interpreter(std::unique_ptr CI, llvm::Error &Err); + Interpreter(std::unique_ptr CI, + const std::string &OrcRuntimePath, llvm::Error &Err); public: ~Interpreter(); static llvm::Expected> - create(std::unique_ptr CI); + create(std::unique_ptr CI, + const std::string &OrcRuntimePath = ""); + static std::string + findOrcRuntimePath(const std::vector &ClangArgv); const CompilerInstance *getCompilerInstance() const; const llvm::orc::LLJIT *getExecutionEngine() const; llvm::Expected Parse(llvm::StringRef Code); Index: clang/lib/Interpreter/IncrementalExecutor.h =================================================================== --- clang/lib/Interpreter/IncrementalExecutor.h +++ clang/lib/Interpreter/IncrementalExecutor.h @@ -44,6 +44,7 @@ enum SymbolNameKind { IRName, LinkerName }; IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, llvm::Error &Err, + const std::string &OrcRuntimePath, const clang::TargetInfo &TI); ~IncrementalExecutor(); Index: clang/lib/Interpreter/IncrementalExecutor.cpp =================================================================== --- clang/lib/Interpreter/IncrementalExecutor.cpp +++ clang/lib/Interpreter/IncrementalExecutor.cpp @@ -17,6 +17,9 @@ #include "clang/Interpreter/PartialTranslationUnit.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" +#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" +#include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" @@ -30,6 +33,7 @@ IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, llvm::Error &Err, + const std::string &OrcRuntimePath, const clang::TargetInfo &TI) : TSCtx(TSC) { using namespace llvm::orc; @@ -37,7 +41,45 @@ auto JTMB = JITTargetMachineBuilder(TI.getTriple()); JTMB.addFeatures(TI.getTargetOpts().Features); - if (auto JitOrErr = LLJITBuilder().setJITTargetMachineBuilder(JTMB).create()) + auto Builder = LLJITBuilder(); + Builder.setJITTargetMachineBuilder(JTMB); + + llvm::orc::ExecutorProcessControl *EPC = nullptr; + if (!OrcRuntimePath.empty()) { + auto EPCOrErr = llvm::orc::SelfExecutorProcessControl::Create( + std::make_shared()); + if (!EPCOrErr) { + Err = EPCOrErr.takeError(); + return; + } + EPC = &**EPCOrErr; + Builder.setObjectLinkingLayerCreator( + [&EPC, OrcRuntimePath](llvm::orc::ExecutionSession &ES, + const llvm::Triple &TT) + -> llvm::Expected> { + auto L = std::make_unique( + ES, EPC->getMemMgr()); + if (OrcRuntimePath.empty()) { + auto EHFrameRegistrar = llvm::orc::EPCEHFrameRegistrar::Create(ES); + if (!EHFrameRegistrar) + return EHFrameRegistrar.takeError(); + auto GDBRegistrar = llvm::orc::createJITLoaderGDBRegistrar(ES); + if (!GDBRegistrar) + return GDBRegistrar.takeError(); + L->addPlugin(std::make_unique( + ES, std::move(*EHFrameRegistrar))); + L->addPlugin(std::make_unique( + ES, std::move(*GDBRegistrar))); + } + return L; + }); + Builder.setExecutorProcessControl(std::move(*EPCOrErr)); + Builder.setPlatformSetUp([OrcRuntimePath](llvm::orc::LLJIT &J) { + return setupOrcPlatform(OrcRuntimePath, J); + }); + } + + if (auto JitOrErr = Builder.create()) Jit = std::move(*JitOrErr); else { Err = JitOrErr.takeError(); Index: clang/lib/Interpreter/Interpreter.cpp =================================================================== --- clang/lib/Interpreter/Interpreter.cpp +++ clang/lib/Interpreter/Interpreter.cpp @@ -175,7 +175,8 @@ } Interpreter::Interpreter(std::unique_ptr CI, - llvm::Error &Err) { + const std::string &OrcRuntimePath, llvm::Error &Err) + : OrcRuntimePath(OrcRuntimePath) { llvm::ErrorAsOutParameter EAO(&Err); auto LLVMCtx = std::make_unique(); TSCtx = std::make_unique(std::move(LLVMCtx)); @@ -183,6 +184,52 @@ *TSCtx->getContext(), Err); } +static std::string buildOrcRTBasename(const llvm::Triple &TT, bool AddArch) { + bool IsITANMSVCWindows = + TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment(); + IsITANMSVCWindows = false; + const char *Prefix = IsITANMSVCWindows ? "" : "lib"; + const char *Suffix = IsITANMSVCWindows ? ".lib" : ".a"; + std::string ArchAndEnv; + if (AddArch) + ArchAndEnv = ("-" + llvm::Triple::getArchTypeName(TT.getArch())).str(); + return (Prefix + Twine("orc_rt") + ArchAndEnv + Suffix).str(); +} + +std::string +Interpreter::findOrcRuntimePath(const std::vector &ClangArgv) { + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagOpts = + CreateAndPopulateDiagOpts(ClangArgv); + TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; + DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); + + driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], + llvm::sys::getProcessTriple(), Diags); + Driver.setCheckInputsExist(false); + llvm::ArrayRef RF = llvm::makeArrayRef(ClangArgv); + std::unique_ptr Compilation(Driver.BuildCompilation(RF)); + + auto RuntimePaths = Compilation->getDefaultToolChain().getRuntimePaths(); + auto &TC = Compilation->getDefaultToolChain(); + auto TT = Compilation->getDefaultToolChain().getTriple(); + for (const auto &LibPath : TC.getLibraryPaths()) { + SmallString<128> P(LibPath); + llvm::sys::path::append(P, buildOrcRTBasename(TT, false)); + if (Driver.getVFS().exists(P)) + return std::string(P.str()); + } + + if (!RuntimePaths.empty()) { + SmallString<256> Path(RuntimePaths.front()); + llvm::sys::path::append(Path, buildOrcRTBasename(TT, true)); + if (Driver.getVFS().exists(Path)) + return Path.str().str(); + } + + return ""; +} + Interpreter::~Interpreter() { if (IncrExecutor) { if (llvm::Error Err = IncrExecutor->cleanUp()) @@ -193,10 +240,11 @@ } llvm::Expected> -Interpreter::create(std::unique_ptr CI) { +Interpreter::create(std::unique_ptr CI, + const std::string &OrcRuntimePath) { llvm::Error Err = llvm::Error::success(); - auto Interp = - std::unique_ptr(new Interpreter(std::move(CI), Err)); + auto Interp = std::unique_ptr( + new Interpreter(std::move(CI), OrcRuntimePath, Err)); if (Err) return std::move(Err); return std::move(Interp); @@ -223,7 +271,8 @@ const clang::TargetInfo &TI = getCompilerInstance()->getASTContext().getTargetInfo(); llvm::Error Err = llvm::Error::success(); - IncrExecutor = std::make_unique(*TSCtx, Err, TI); + IncrExecutor = + std::make_unique(*TSCtx, Err, OrcRuntimePath, TI); if (Err) return Err; Index: clang/tools/clang-repl/ClangRepl.cpp =================================================================== --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -18,6 +18,7 @@ #include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/LineEditor/LineEditor.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Host.h" #include "llvm/Support/ManagedStatic.h" // llvm_shutdown #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" // llvm::Initialize* @@ -65,6 +66,16 @@ return (Errs || HasError) ? EXIT_FAILURE : EXIT_SUCCESS; } +/// Returns true when it could find orc runtime archive from clang resource +/// directory and using orc runtime is preferred. +static bool isOrcRuntimeSupported(const std::vector &ClangArgv) { + auto OrcRuntimePath = clang::Interpreter::findOrcRuntimePath(ClangArgv); + if (OrcRuntimePath.empty()) + return false; + auto TT = llvm::Triple(llvm::sys::getProcessTriple()); + return TT.isWindowsMSVCEnvironment() && TT.getArch() == llvm::Triple::x86_64; +} + llvm::ExitOnError ExitOnErr; int main(int argc, const char **argv) { ExitOnErr.setBanner("clang-repl: "); @@ -101,7 +112,11 @@ // Load any requested plugins. CI->LoadRequestedPlugins(); - auto Interp = ExitOnErr(clang::Interpreter::create(std::move(CI))); + auto OrcRuntimePath = isOrcRuntimeSupported(ClangArgv) + ? clang::Interpreter::findOrcRuntimePath(ClangArgv) + : ""; + auto Interp = + ExitOnErr(clang::Interpreter::create(std::move(CI), OrcRuntimePath)); for (const std::string &input : OptInputs) { if (auto Err = Interp->ParseAndExecute(input)) llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");