xref: /llvm-project/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp (revision a72d7eea5413444249670579fecea6823fb3c564)
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