brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.1 KiB · 704ddc3 Raw
203 lines · cpp
1//===- unittests/Interpreter/OutOfProcessInterpreterTest.cpp --- Interpreter2// tests when Out-of-Process ----===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9//10// Unit tests for Clang's Interpreter library.11//12//===----------------------------------------------------------------------===//13 14#include "InterpreterTestFixture.h"15#include "clang/AST/Decl.h"16#include "clang/AST/DeclGroup.h"17#include "clang/AST/Mangle.h"18#include "clang/Basic/Version.h"19#include "clang/Config/config.h"20#include "clang/Frontend/CompilerInstance.h"21#include "clang/Frontend/TextDiagnosticPrinter.h"22#include "clang/Interpreter/Interpreter.h"23#include "clang/Interpreter/Value.h"24#include "clang/Sema/Lookup.h"25#include "clang/Sema/Sema.h"26#include "llvm/Support/Error.h"27#include "llvm/TargetParser/Host.h"28#include "gmock/gmock.h"29#include "gtest/gtest.h"30#include <memory>31#include <signal.h>32#include <sstream>33#include <unistd.h>34 35using namespace clang;36 37llvm::ExitOnError ExitOnError;38 39namespace {40 41using Args = std::vector<const char *>;42 43struct FileDeleter {44  void operator()(FILE *f) {45    if (f)46      fclose(f);47  }48};49 50struct IOContext {51  std::unique_ptr<FILE, FileDeleter> stdin_file;52  std::unique_ptr<FILE, FileDeleter> stdout_file;53  std::unique_ptr<FILE, FileDeleter> stderr_file;54 55  bool initializeTempFiles() {56    stdin_file.reset(tmpfile());57    stdout_file.reset(tmpfile());58    stderr_file.reset(tmpfile());59    return stdin_file && stdout_file && stderr_file;60  }61 62  std::string readStdoutContent() {63    if (!stdout_file)64      return "";65    rewind(stdout_file.get());66    std::ostringstream content;67    char buffer[1024];68    size_t bytes_read;69    while ((bytes_read = fread(buffer, 1, sizeof(buffer), stdout_file.get())) >70           0) {71      content.write(buffer, bytes_read);72    }73    return content.str();74  }75 76  std::string readStderrContent() {77    if (!stderr_file)78      return "";79    rewind(stderr_file.get());80    std::ostringstream content;81    char buffer[1024];82    size_t bytes_read;83    while ((bytes_read = fread(buffer, 1, sizeof(buffer), stderr_file.get())) >84           0) {85      content.write(buffer, bytes_read);86    }87    return content.str();88  }89};90 91static void removePathComponent(unsigned N, llvm::SmallString<256> &Path) {92  for (unsigned i = 0; i < N; ++i)93    llvm::sys::path::remove_filename(Path);94}95 96static std::string getExecutorPath() {97  llvm::SmallString<256> ExecutorPath(llvm::sys::fs::getMainExecutable(98      nullptr, reinterpret_cast<void *>(&getExecutorPath)));99  removePathComponent(5, ExecutorPath);100  llvm::sys::path::append(ExecutorPath, "bin", "llvm-jitlink-executor");101  return ExecutorPath.str().str();102}103 104static std::string getOrcRuntimePath() {105  llvm::SmallString<256> RuntimePath(llvm::sys::fs::getMainExecutable(106      nullptr, reinterpret_cast<void *>(&getOrcRuntimePath)));107  removePathComponent(5, RuntimePath);108  llvm::sys::path::append(RuntimePath, CLANG_INSTALL_LIBDIR_BASENAME, "clang",109                          CLANG_VERSION_MAJOR_STRING, "lib");110 111  llvm::Triple SystemTriple(llvm::sys::getProcessTriple());112  if (SystemTriple.isOSBinFormatMachO()) {113    llvm::sys::path::append(RuntimePath, "darwin", "liborc_rt_osx.a");114  } else if (SystemTriple.isOSBinFormatELF()) {115    llvm::sys::path::append(RuntimePath, "x86_64-unknown-linux-gnu",116                            "liborc_rt.a");117  }118  return RuntimePath.str().str();119}120 121static std::unique_ptr<Interpreter>122createInterpreterWithRemoteExecution(std::shared_ptr<IOContext> io_ctx,123                                     const Args &ExtraArgs = {}) {124  Args ClangArgs = {"-Xclang", "-emit-llvm-only"};125  llvm::append_range(ClangArgs, ExtraArgs);126  auto CB = clang::IncrementalCompilerBuilder();127  CB.SetCompilerArgs(ClangArgs);128  auto CI = cantFail(CB.CreateCpp());129 130  clang::Interpreter::JITConfig Config;131  llvm::Triple SystemTriple(llvm::sys::getProcessTriple());132 133  if (SystemTriple.isOSBinFormatELF() || SystemTriple.isOSBinFormatMachO()) {134    Config.IsOutOfProcess = true;135    Config.OOPExecutor = getExecutorPath();136    Config.UseSharedMemory = false;137    Config.SlabAllocateSize = 0;138    Config.OrcRuntimePath = getOrcRuntimePath();139 140    int stdin_fd = fileno(io_ctx->stdin_file.get());141    int stdout_fd = fileno(io_ctx->stdout_file.get());142    int stderr_fd = fileno(io_ctx->stderr_file.get());143 144    Config.CustomizeFork = [=] {145      auto redirect = [](int from, int to) {146        if (from != to) {147          dup2(from, to);148          close(from);149        }150      };151 152      redirect(stdin_fd, STDIN_FILENO);153      redirect(stdout_fd, STDOUT_FILENO);154      redirect(stderr_fd, STDERR_FILENO);155 156      setvbuf(stdout, nullptr, _IONBF, 0);157      setvbuf(stderr, nullptr, _IONBF, 0);158 159      printf("CustomizeFork executed\n");160      fflush(stdout);161    };162  }163 164  return cantFail(clang::Interpreter::create(std::move(CI), Config));165}166 167static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {168  return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());169}170 171TEST_F(InterpreterTestBase, SanityWithRemoteExecution) {172  if (!HostSupportsJIT())173    GTEST_SKIP();174 175  std::string OrcRuntimePath = getOrcRuntimePath();176  std::string ExecutorPath = getExecutorPath();177 178  if (!llvm::sys::fs::exists(OrcRuntimePath) ||179      !llvm::sys::fs::exists(ExecutorPath))180    GTEST_SKIP();181 182  auto io_ctx = std::make_shared<IOContext>();183  ASSERT_TRUE(io_ctx->initializeTempFiles());184 185  std::unique_ptr<Interpreter> Interp =186      createInterpreterWithRemoteExecution(io_ctx);187  ASSERT_TRUE(Interp);188 189  using PTU = PartialTranslationUnit;190  PTU &R1(cantFail(Interp->Parse("void g(); void g() {}")));191  EXPECT_EQ(2U, DeclsSize(R1.TUPart));192 193  PTU &R2(cantFail(Interp->Parse("int i = 42;")));194  EXPECT_EQ(1U, DeclsSize(R2.TUPart));195 196  std::string captured_stdout = io_ctx->readStdoutContent();197  std::string captured_stderr = io_ctx->readStderrContent();198 199  EXPECT_TRUE(captured_stdout.find("CustomizeFork executed") !=200              std::string::npos);201}202 203} // end anonymous namespace