brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.8 KiB · f50f6e3 Raw
180 lines · cpp
1//===- unittests/Interpreter/InterpreterExtensionsTest.cpp ----------------===//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// Unit tests for Clang's Interpreter library.10//11//===----------------------------------------------------------------------===//12 13#include "InterpreterTestFixture.h"14 15#include "clang/Interpreter/Interpreter.h"16 17#include "clang/AST/Expr.h"18#include "clang/Frontend/CompilerInstance.h"19#include "clang/Sema/Lookup.h"20#include "clang/Sema/Sema.h"21 22#include "llvm/ExecutionEngine/Orc/LLJIT.h"23#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"24#include "llvm/MC/TargetRegistry.h"25#include "llvm/Support/Threading.h"26#include "llvm/Testing/Support/Error.h"27 28#include "gmock/gmock.h"29#include "gtest/gtest.h"30 31#include <system_error>32 33#if defined(_AIX) || defined(__MVS__)34#define CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT35#endif36 37using namespace clang;38namespace {39 40class InterpreterExtensionsTest : public InterpreterTestBase {41protected:42  void SetUp() override {43#ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT44    GTEST_SKIP();45#endif46  }47 48  static void SetUpTestSuite() {49    llvm::InitializeAllTargets();50    llvm::InitializeAllTargetInfos();51    llvm::InitializeAllTargetMCs();52    llvm::InitializeAllAsmPrinters();53  }54 55public:56  // Some tests require a arm-registered-target57  static bool IsARMTargetRegistered() {58    llvm::Triple TT;59    TT.setArch(llvm::Triple::arm);60    TT.setVendor(llvm::Triple::UnknownVendor);61    TT.setOS(llvm::Triple::UnknownOS);62 63    std::string UnusedErr;64    return llvm::TargetRegistry::lookupTarget(TT, UnusedErr);65  }66};67 68struct OutOfProcInterpreter : public Interpreter {69  OutOfProcInterpreter(70      std::unique_ptr<CompilerInstance> CI, llvm::Error &ErrOut,71      std::unique_ptr<clang::ASTConsumer> Consumer,72      std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr)73      : Interpreter(std::move(CI), ErrOut, std::move(JITBuilder),74                    std::move(Consumer)) {}75};76 77TEST_F(InterpreterExtensionsTest, FindRuntimeInterface) {78// FIXME : WebAssembly doesn't currently support Jit (see79// https: // github.com/llvm/llvm-project/pull/150977#discussion_r2237521095).80// so this check of HostSupportsJIT has been skipped81// over until support is added, and HostSupportsJIT can return true.82#ifndef __EMSCRIPTEN__83  if (!HostSupportsJIT())84    GTEST_SKIP();85#endif86  clang::IncrementalCompilerBuilder CB;87  llvm::Error ErrOut = llvm::Error::success();88  auto CI = cantFail(CB.CreateCpp());89  // Do not attach the default consumer which is specialized for in-process.90  class NoopConsumer : public ASTConsumer {};91  std::unique_ptr<ASTConsumer> C = std::make_unique<NoopConsumer>();92  OutOfProcInterpreter I(std::move(CI), ErrOut, std::move(C),93                         /*JITBuilder=*/nullptr);94  cantFail(std::move(ErrOut));95  cantFail(I.Parse("int a = 1; a"));96  cantFail(I.Parse("int b = 2; b"));97  cantFail(I.Parse("int c = 3; c"));98 99  // Make sure no clang::Value logic is attached by the Interpreter.100  Value V1;101  llvm::cantFail(I.ParseAndExecute("int x = 42;"));102  llvm::cantFail(I.ParseAndExecute("x", &V1));103  EXPECT_FALSE(V1.isValid());104  EXPECT_FALSE(V1.hasValue());105}106 107class CustomJBInterpreter : public Interpreter {108  using CustomJITBuilderCreatorFunction =109      std::function<llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>()>;110  CustomJITBuilderCreatorFunction JBCreator = nullptr;111 112public:113  CustomJBInterpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &ErrOut,114                      std::unique_ptr<llvm::orc::LLJITBuilder> JB)115      : Interpreter(std::move(CI), ErrOut, std::move(JB)) {}116 117  ~CustomJBInterpreter() override {118    // Skip cleanUp() because it would trigger LLJIT default dtors119    Interpreter::ResetExecutor();120  }121 122  llvm::Error CreateExecutor() { return Interpreter::CreateExecutor(); }123};124 125TEST_F(InterpreterExtensionsTest, DefaultCrossJIT) {126  if (!IsARMTargetRegistered())127    GTEST_SKIP();128 129  IncrementalCompilerBuilder CB;130  CB.SetTargetTriple("armv6-none-eabi");131  auto CI = cantFail(CB.CreateCpp());132  llvm::Error ErrOut = llvm::Error::success();133  CustomJBInterpreter Interp(std::move(CI), ErrOut, nullptr);134  cantFail(std::move(ErrOut));135}136 137TEST_F(InterpreterExtensionsTest, CustomCrossJIT) {138  if (!IsARMTargetRegistered())139    GTEST_SKIP();140 141  std::string TargetTriple = "armv6-none-eabi";142 143  IncrementalCompilerBuilder CB;144  CB.SetTargetTriple(TargetTriple);145  auto CI = cantFail(CB.CreateCpp());146 147  using namespace llvm::orc;148  LLJIT *JIT = nullptr;149  std::vector<std::unique_ptr<llvm::MemoryBuffer>> Objs;150  auto JTMB = JITTargetMachineBuilder(llvm::Triple(TargetTriple));151  JTMB.setCPU("cortex-m0plus");152 153  auto JB = std::make_unique<LLJITBuilder>();154  JB->setJITTargetMachineBuilder(JTMB);155  JB->setPlatformSetUp(setUpInactivePlatform);156  JB->setNotifyCreatedCallback([&](LLJIT &J) {157    ObjectLayer &ObjLayer = J.getObjLinkingLayer();158    auto *JITLinkObjLayer = llvm::dyn_cast<ObjectLinkingLayer>(&ObjLayer);159    JITLinkObjLayer->setReturnObjectBuffer(160        [&Objs](std::unique_ptr<llvm::MemoryBuffer> MB) {161          Objs.push_back(std::move(MB));162        });163    JIT = &J;164    return llvm::Error::success();165  });166 167  llvm::Error ErrOut = llvm::Error::success();168  CustomJBInterpreter Interp(std::move(CI), ErrOut, std::move(JB));169  cantFail(std::move(ErrOut));170 171  EXPECT_EQ(0U, Objs.size());172  cantFail(Interp.ParseAndExecute("int a = 1;"));173  ASSERT_NE(JIT, nullptr); // But it is, because JBCreator was never called174  ExecutorAddr Addr = cantFail(JIT->lookup("a"));175  EXPECT_NE(0U, Addr.getValue());176  EXPECT_EQ(1U, Objs.size());177}178 179} // end anonymous namespace180