1ec2875ceSStefan Gränitz //===- unittests/Interpreter/InterpreterExtensionsTest.cpp ----------------===// 2ec2875ceSStefan Gränitz // 3ec2875ceSStefan Gränitz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ec2875ceSStefan Gränitz // See https://llvm.org/LICENSE.txt for license information. 5ec2875ceSStefan Gränitz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ec2875ceSStefan Gränitz // 7ec2875ceSStefan Gränitz //===----------------------------------------------------------------------===// 8ec2875ceSStefan Gränitz // 9ec2875ceSStefan Gränitz // Unit tests for Clang's Interpreter library. 10ec2875ceSStefan Gränitz // 11ec2875ceSStefan Gränitz //===----------------------------------------------------------------------===// 12ec2875ceSStefan Gränitz 13a871470aSStefan Gränitz #include "InterpreterTestFixture.h" 14a871470aSStefan Gränitz 15ec2875ceSStefan Gränitz #include "clang/Interpreter/Interpreter.h" 16ec2875ceSStefan Gränitz 17ec2875ceSStefan Gränitz #include "clang/AST/Expr.h" 18ec2875ceSStefan Gränitz #include "clang/Frontend/CompilerInstance.h" 19ec2875ceSStefan Gränitz #include "clang/Sema/Lookup.h" 20ec2875ceSStefan Gränitz #include "clang/Sema/Sema.h" 21ec2875ceSStefan Gränitz 22d73c2d5dSStefan Gränitz #include "llvm/ExecutionEngine/Orc/LLJIT.h" 230cf4788dSStefan Gränitz #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" 2413078cbcSStefan Gränitz #include "llvm/MC/TargetRegistry.h" 250cf4788dSStefan Gränitz #include "llvm/Support/Threading.h" 26ec2875ceSStefan Gränitz #include "llvm/Testing/Support/Error.h" 27ec2875ceSStefan Gränitz 28ec2875ceSStefan Gränitz #include "gmock/gmock.h" 29ec2875ceSStefan Gränitz #include "gtest/gtest.h" 300cf4788dSStefan Gränitz 31ec2875ceSStefan Gränitz #include <system_error> 32ec2875ceSStefan Gränitz 338c6e0459Sbahareh-farhadi #if defined(_AIX) || defined(__MVS__) 340cf4788dSStefan Gränitz #define CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 350cf4788dSStefan Gränitz #endif 360cf4788dSStefan Gränitz 37ec2875ceSStefan Gränitz using namespace clang; 38ec2875ceSStefan Gränitz namespace { 39ec2875ceSStefan Gränitz 40a871470aSStefan Gränitz class InterpreterExtensionsTest : public InterpreterTestBase { 41a871470aSStefan Gränitz protected: 42a871470aSStefan Gränitz void SetUp() override { 43a871470aSStefan Gränitz #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 44a871470aSStefan Gränitz GTEST_SKIP(); 45a871470aSStefan Gränitz #endif 46d73c2d5dSStefan Gränitz } 47d73c2d5dSStefan Gränitz 48a871470aSStefan Gränitz static void SetUpTestSuite() { 49a871470aSStefan Gränitz llvm::InitializeAllTargets(); 50a871470aSStefan Gränitz llvm::InitializeAllTargetInfos(); 51a871470aSStefan Gränitz llvm::InitializeAllTargetMCs(); 52a871470aSStefan Gränitz llvm::InitializeAllAsmPrinters(); 53a871470aSStefan Gränitz } 54a871470aSStefan Gränitz 55a871470aSStefan Gränitz public: 5613078cbcSStefan Gränitz // Some tests require a arm-registered-target 5713078cbcSStefan Gränitz static bool IsARMTargetRegistered() { 5813078cbcSStefan Gränitz llvm::Triple TT; 5913078cbcSStefan Gränitz TT.setArch(llvm::Triple::arm); 6013078cbcSStefan Gränitz TT.setVendor(llvm::Triple::UnknownVendor); 6113078cbcSStefan Gränitz TT.setOS(llvm::Triple::UnknownOS); 6213078cbcSStefan Gränitz 6313078cbcSStefan Gränitz std::string UnusedErr; 6413078cbcSStefan Gränitz return llvm::TargetRegistry::lookupTarget(TT.str(), UnusedErr); 6513078cbcSStefan Gränitz } 66a871470aSStefan Gränitz }; 67d73c2d5dSStefan Gränitz 68*a72d7eeaSVassil Vassilev struct OutOfProcInterpreter : public Interpreter { 69*a72d7eeaSVassil Vassilev OutOfProcInterpreter( 70*a72d7eeaSVassil Vassilev std::unique_ptr<CompilerInstance> CI, llvm::Error &ErrOut, 71*a72d7eeaSVassil Vassilev std::unique_ptr<clang::ASTConsumer> Consumer, 72*a72d7eeaSVassil Vassilev std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr) 73*a72d7eeaSVassil Vassilev : Interpreter(std::move(CI), ErrOut, std::move(JITBuilder), 74*a72d7eeaSVassil Vassilev std::move(Consumer)) {} 75ec2875ceSStefan Gränitz }; 76ec2875ceSStefan Gränitz 77a871470aSStefan Gränitz TEST_F(InterpreterExtensionsTest, FindRuntimeInterface) { 78a871470aSStefan Gränitz if (!HostSupportsJIT()) 7998f9bb38SStefan Gränitz GTEST_SKIP(); 8098f9bb38SStefan Gränitz 81ec2875ceSStefan Gränitz clang::IncrementalCompilerBuilder CB; 82ec2875ceSStefan Gränitz llvm::Error ErrOut = llvm::Error::success(); 83*a72d7eeaSVassil Vassilev auto CI = cantFail(CB.CreateCpp()); 84*a72d7eeaSVassil Vassilev // Do not attach the default consumer which is specialized for in-process. 85*a72d7eeaSVassil Vassilev class NoopConsumer : public ASTConsumer {}; 86*a72d7eeaSVassil Vassilev std::unique_ptr<ASTConsumer> C = std::make_unique<NoopConsumer>(); 87*a72d7eeaSVassil Vassilev OutOfProcInterpreter I(std::move(CI), ErrOut, std::move(C), 88*a72d7eeaSVassil Vassilev /*JITBuilder=*/nullptr); 89ec2875ceSStefan Gränitz cantFail(std::move(ErrOut)); 90*a72d7eeaSVassil Vassilev cantFail(I.Parse("int a = 1; a")); 91*a72d7eeaSVassil Vassilev cantFail(I.Parse("int b = 2; b")); 92*a72d7eeaSVassil Vassilev cantFail(I.Parse("int c = 3; c")); 93*a72d7eeaSVassil Vassilev 94*a72d7eeaSVassil Vassilev // Make sure no clang::Value logic is attached by the Interpreter. 95*a72d7eeaSVassil Vassilev Value V1; 96*a72d7eeaSVassil Vassilev llvm::cantFail(I.ParseAndExecute("int x = 42;")); 97*a72d7eeaSVassil Vassilev llvm::cantFail(I.ParseAndExecute("x", &V1)); 98*a72d7eeaSVassil Vassilev EXPECT_FALSE(V1.isValid()); 99*a72d7eeaSVassil Vassilev EXPECT_FALSE(V1.hasValue()); 100ec2875ceSStefan Gränitz } 101ec2875ceSStefan Gränitz 1020cf4788dSStefan Gränitz class CustomJBInterpreter : public Interpreter { 1030cf4788dSStefan Gränitz using CustomJITBuilderCreatorFunction = 1040cf4788dSStefan Gränitz std::function<llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>()>; 1050cf4788dSStefan Gränitz CustomJITBuilderCreatorFunction JBCreator = nullptr; 1060cf4788dSStefan Gränitz 1070cf4788dSStefan Gränitz public: 108cb7995a1SStefan Gränitz CustomJBInterpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &ErrOut, 109cb7995a1SStefan Gränitz std::unique_ptr<llvm::orc::LLJITBuilder> JB) 110cb7995a1SStefan Gränitz : Interpreter(std::move(CI), ErrOut, std::move(JB)) {} 1110cf4788dSStefan Gränitz 1120cf4788dSStefan Gränitz ~CustomJBInterpreter() override { 1130cf4788dSStefan Gränitz // Skip cleanUp() because it would trigger LLJIT default dtors 1140cf4788dSStefan Gränitz Interpreter::ResetExecutor(); 1150cf4788dSStefan Gränitz } 1160cf4788dSStefan Gränitz 1170cf4788dSStefan Gränitz llvm::Error CreateExecutor() { return Interpreter::CreateExecutor(); } 1180cf4788dSStefan Gränitz }; 1190cf4788dSStefan Gränitz 120a871470aSStefan Gränitz TEST_F(InterpreterExtensionsTest, DefaultCrossJIT) { 12113078cbcSStefan Gränitz if (!IsARMTargetRegistered()) 12213078cbcSStefan Gränitz GTEST_SKIP(); 12313078cbcSStefan Gränitz 1240cf4788dSStefan Gränitz IncrementalCompilerBuilder CB; 1250cf4788dSStefan Gränitz CB.SetTargetTriple("armv6-none-eabi"); 1260cf4788dSStefan Gränitz auto CI = cantFail(CB.CreateCpp()); 1270cf4788dSStefan Gränitz llvm::Error ErrOut = llvm::Error::success(); 128cb7995a1SStefan Gränitz CustomJBInterpreter Interp(std::move(CI), ErrOut, nullptr); 1290cf4788dSStefan Gränitz cantFail(std::move(ErrOut)); 1300cf4788dSStefan Gränitz } 1310cf4788dSStefan Gränitz 132a871470aSStefan Gränitz TEST_F(InterpreterExtensionsTest, CustomCrossJIT) { 13313078cbcSStefan Gränitz if (!IsARMTargetRegistered()) 13413078cbcSStefan Gränitz GTEST_SKIP(); 13513078cbcSStefan Gränitz 1360cf4788dSStefan Gränitz std::string TargetTriple = "armv6-none-eabi"; 1370cf4788dSStefan Gränitz 1380cf4788dSStefan Gränitz IncrementalCompilerBuilder CB; 1390cf4788dSStefan Gränitz CB.SetTargetTriple(TargetTriple); 1400cf4788dSStefan Gränitz auto CI = cantFail(CB.CreateCpp()); 1410cf4788dSStefan Gränitz 1420cf4788dSStefan Gränitz using namespace llvm::orc; 1430cf4788dSStefan Gränitz LLJIT *JIT = nullptr; 1440cf4788dSStefan Gränitz std::vector<std::unique_ptr<llvm::MemoryBuffer>> Objs; 1450cf4788dSStefan Gränitz auto JTMB = JITTargetMachineBuilder(llvm::Triple(TargetTriple)); 1460cf4788dSStefan Gränitz JTMB.setCPU("cortex-m0plus"); 147cb7995a1SStefan Gränitz 1480cf4788dSStefan Gränitz auto JB = std::make_unique<LLJITBuilder>(); 1490cf4788dSStefan Gränitz JB->setJITTargetMachineBuilder(JTMB); 1500cf4788dSStefan Gränitz JB->setPlatformSetUp(setUpInactivePlatform); 1510cf4788dSStefan Gränitz JB->setNotifyCreatedCallback([&](LLJIT &J) { 1520cf4788dSStefan Gränitz ObjectLayer &ObjLayer = J.getObjLinkingLayer(); 1530cf4788dSStefan Gränitz auto *JITLinkObjLayer = llvm::dyn_cast<ObjectLinkingLayer>(&ObjLayer); 1540cf4788dSStefan Gränitz JITLinkObjLayer->setReturnObjectBuffer( 1550cf4788dSStefan Gränitz [&Objs](std::unique_ptr<llvm::MemoryBuffer> MB) { 1560cf4788dSStefan Gränitz Objs.push_back(std::move(MB)); 1570cf4788dSStefan Gränitz }); 1580cf4788dSStefan Gränitz JIT = &J; 1590cf4788dSStefan Gränitz return llvm::Error::success(); 1600cf4788dSStefan Gränitz }); 161cb7995a1SStefan Gränitz 162cb7995a1SStefan Gränitz llvm::Error ErrOut = llvm::Error::success(); 163cb7995a1SStefan Gränitz CustomJBInterpreter Interp(std::move(CI), ErrOut, std::move(JB)); 164cb7995a1SStefan Gränitz cantFail(std::move(ErrOut)); 1650cf4788dSStefan Gränitz 1660cf4788dSStefan Gränitz EXPECT_EQ(0U, Objs.size()); 1670cf4788dSStefan Gränitz cantFail(Interp.ParseAndExecute("int a = 1;")); 168cb7995a1SStefan Gränitz ASSERT_NE(JIT, nullptr); // But it is, because JBCreator was never called 1690cf4788dSStefan Gränitz ExecutorAddr Addr = cantFail(JIT->lookup("a")); 1700cf4788dSStefan Gränitz EXPECT_NE(0U, Addr.getValue()); 1710cf4788dSStefan Gränitz EXPECT_EQ(1U, Objs.size()); 1720cf4788dSStefan Gränitz } 1730cf4788dSStefan Gränitz 174ec2875ceSStefan Gränitz } // end anonymous namespace 175