================ @@ -0,0 +1,183 @@ +//===- unittests/Interpreter/OutOfProcessInterpreterTest.cpp --- Interpreter +// tests when Out-of-Process ----===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Unit tests for Clang's Interpreter library. +// +//===----------------------------------------------------------------------===// + +#include "InterpreterTestFixture.h" + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclGroup.h" +#include "clang/AST/Mangle.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticIDs.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/Version.h" +#include "clang/Config/config.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/ToolChain.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Interpreter/Interpreter.h" +#include "clang/Interpreter/RemoteJITUtils.h" +#include "clang/Interpreter/Value.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Sema.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" +#include "llvm/TargetParser/Host.h" +#include "llvm/TargetParser/Triple.h" + +#include "llvm/TargetParser/Host.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; + +llvm::ExitOnError ExitOnError; + +#ifdef _WIN32 +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +#endif + +namespace { + +using Args = std::vector<const char *>; + +static void removePathComponent(unsigned N, llvm::SmallString<256> &Path) { + for (unsigned i = 0; i < N; ++i) + llvm::sys::path::remove_filename(Path); +} + +static std::string getExecutorPath() { + llvm::SmallString<256> ExecutorPath(llvm::sys::fs::getMainExecutable( + nullptr, reinterpret_cast<void *>(&getExecutorPath))); + removePathComponent(5, ExecutorPath); + llvm::sys::path::append(ExecutorPath, "bin", "llvm-jitlink-executor"); + return ExecutorPath.str().str(); +} + +static std::string getCompilerRTPath() { + clang::DiagnosticOptions DiagOpts; + llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID( + new clang::DiagnosticIDs()); + + clang::IgnoringDiagConsumer DiagConsumer; + clang::DiagnosticsEngine Diags(DiagID, DiagOpts, &DiagConsumer, false); + std::vector<const char *> Args = {"clang", "--version"}; + clang::driver::Driver D("clang", llvm::sys::getProcessTriple(), Diags); + D.setCheckInputsExist(false); + + std::unique_ptr<clang::driver::Compilation> C(D.BuildCompilation(Args)); + if (!C) { + return ""; + } + + const clang::driver::ToolChain &TC = C->getDefaultToolChain(); + std::optional<std::string> CompilerRTPath = TC.getCompilerRTPath(); + + return CompilerRTPath ? *CompilerRTPath : ""; +} + +static std::string getOrcRuntimePath(std::string CompilerRTPath) { + llvm::SmallString<256> BasePath(llvm::sys::fs::getMainExecutable( + nullptr, reinterpret_cast<void *>(&getOrcRuntimePath))); + removePathComponent(5, BasePath); + llvm::sys::path::append(BasePath, CompilerRTPath); + std::string OrcRuntimePath; + if (llvm::sys::fs::exists(BasePath.str().str() + "/liborc_rt.a")) { + OrcRuntimePath = BasePath.str().str() + "/liborc_rt.a"; + } else if (llvm::sys::fs::exists(BasePath.str().str() + "/liborc_rt_osx.a")) { + OrcRuntimePath = BasePath.str().str() + "/liborc_rt_osx.a"; + } else if (llvm::sys::fs::exists(BasePath.str().str() + + "/liborc_rt-x86_64.a")) { + OrcRuntimePath = BasePath.str().str() + "/liborc_rt-x86_64.a"; + } + return OrcRuntimePath; +} + +static std::unique_ptr<Interpreter> +createInterpreterWithRemoteExecution(const Args &ExtraArgs = {}, + DiagnosticConsumer *Client = nullptr) { + Args ClangArgs = {"-Xclang", "-emit-llvm-only"}; + llvm::append_range(ClangArgs, ExtraArgs); + auto CB = clang::IncrementalCompilerBuilder(); + CB.SetCompilerArgs(ClangArgs); + auto CI = cantFail(CB.CreateCpp()); + if (Client) + CI->getDiagnostics().setClient(Client, /*ShouldOwnClient=*/false); + + std::unique_ptr<llvm::orc::LLJITBuilder> JB; + + llvm::Triple SystemTriple(llvm::sys::getProcessTriple()); + + std::string CompilerRTPath = getCompilerRTPath(); + + if ((SystemTriple.isOSBinFormatELF() || SystemTriple.isOSBinFormatMachO())) { + std::string OOPExecutor = getExecutorPath(); + std::string OrcRuntimePath = getOrcRuntimePath(CompilerRTPath); + bool UseSharedMemory = false; + std::string SlabAllocateSizeString = ""; + std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC; + EPC = ExitOnError(launchExecutor(OOPExecutor, UseSharedMemory, + SlabAllocateSizeString, + [=] { // Lambda defined inline + auto redirect = [](int from, int to) { + if (from != to) { + dup2(from, to); + close(from); + } + }; + + redirect(0, STDIN_FILENO); + redirect(1, STDOUT_FILENO); + redirect(2, STDERR_FILENO); + + setvbuf(stdout, nullptr, _IONBF, 0); + setvbuf(stderr, nullptr, _IONBF, 0); + })); + if (EPC) { + CB.SetTargetTriple(EPC->getTargetTriple().getTriple()); + JB = ExitOnError(clang::Interpreter::createLLJITBuilder(std::move(EPC), + OrcRuntimePath)); + } + } + + return cantFail(clang::Interpreter::create(std::move(CI), std::move(JB))); ---------------- vgvassilev wrote:
All of that should go in Interpreter.cpp logic when `IsOutOfProcess` is set. This way we won't have to drag `OrcRuntimePath` around. https://github.com/llvm/llvm-project/pull/155140 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
