xref: /llvm-project/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp (revision a72d7eea5413444249670579fecea6823fb3c564)
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-exception
6 //
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_LLJIT
35 #endif
36 
37 using namespace clang;
38 namespace {
39 
40 class InterpreterExtensionsTest : public InterpreterTestBase {
41 protected:
42   void SetUp() override {
43 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
44     GTEST_SKIP();
45 #endif
46   }
47 
48   static void SetUpTestSuite() {
49     llvm::InitializeAllTargets();
50     llvm::InitializeAllTargetInfos();
51     llvm::InitializeAllTargetMCs();
52     llvm::InitializeAllAsmPrinters();
53   }
54 
55 public:
56   // Some tests require a arm-registered-target
57   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.str(), UnusedErr);
65   }
66 };
67 
68 struct 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 
77 TEST_F(InterpreterExtensionsTest, FindRuntimeInterface) {
78   if (!HostSupportsJIT())
79     GTEST_SKIP();
80 
81   clang::IncrementalCompilerBuilder CB;
82   llvm::Error ErrOut = llvm::Error::success();
83   auto CI = cantFail(CB.CreateCpp());
84   // Do not attach the default consumer which is specialized for in-process.
85   class NoopConsumer : public ASTConsumer {};
86   std::unique_ptr<ASTConsumer> C = std::make_unique<NoopConsumer>();
87   OutOfProcInterpreter I(std::move(CI), ErrOut, std::move(C),
88                          /*JITBuilder=*/nullptr);
89   cantFail(std::move(ErrOut));
90   cantFail(I.Parse("int a = 1; a"));
91   cantFail(I.Parse("int b = 2; b"));
92   cantFail(I.Parse("int c = 3; c"));
93 
94   // Make sure no clang::Value logic is attached by the Interpreter.
95   Value V1;
96   llvm::cantFail(I.ParseAndExecute("int x = 42;"));
97   llvm::cantFail(I.ParseAndExecute("x", &V1));
98   EXPECT_FALSE(V1.isValid());
99   EXPECT_FALSE(V1.hasValue());
100 }
101 
102 class CustomJBInterpreter : public Interpreter {
103   using CustomJITBuilderCreatorFunction =
104       std::function<llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>()>;
105   CustomJITBuilderCreatorFunction JBCreator = nullptr;
106 
107 public:
108   CustomJBInterpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &ErrOut,
109                       std::unique_ptr<llvm::orc::LLJITBuilder> JB)
110       : Interpreter(std::move(CI), ErrOut, std::move(JB)) {}
111 
112   ~CustomJBInterpreter() override {
113     // Skip cleanUp() because it would trigger LLJIT default dtors
114     Interpreter::ResetExecutor();
115   }
116 
117   llvm::Error CreateExecutor() { return Interpreter::CreateExecutor(); }
118 };
119 
120 TEST_F(InterpreterExtensionsTest, DefaultCrossJIT) {
121   if (!IsARMTargetRegistered())
122     GTEST_SKIP();
123 
124   IncrementalCompilerBuilder CB;
125   CB.SetTargetTriple("armv6-none-eabi");
126   auto CI = cantFail(CB.CreateCpp());
127   llvm::Error ErrOut = llvm::Error::success();
128   CustomJBInterpreter Interp(std::move(CI), ErrOut, nullptr);
129   cantFail(std::move(ErrOut));
130 }
131 
132 TEST_F(InterpreterExtensionsTest, CustomCrossJIT) {
133   if (!IsARMTargetRegistered())
134     GTEST_SKIP();
135 
136   std::string TargetTriple = "armv6-none-eabi";
137 
138   IncrementalCompilerBuilder CB;
139   CB.SetTargetTriple(TargetTriple);
140   auto CI = cantFail(CB.CreateCpp());
141 
142   using namespace llvm::orc;
143   LLJIT *JIT = nullptr;
144   std::vector<std::unique_ptr<llvm::MemoryBuffer>> Objs;
145   auto JTMB = JITTargetMachineBuilder(llvm::Triple(TargetTriple));
146   JTMB.setCPU("cortex-m0plus");
147 
148   auto JB = std::make_unique<LLJITBuilder>();
149   JB->setJITTargetMachineBuilder(JTMB);
150   JB->setPlatformSetUp(setUpInactivePlatform);
151   JB->setNotifyCreatedCallback([&](LLJIT &J) {
152     ObjectLayer &ObjLayer = J.getObjLinkingLayer();
153     auto *JITLinkObjLayer = llvm::dyn_cast<ObjectLinkingLayer>(&ObjLayer);
154     JITLinkObjLayer->setReturnObjectBuffer(
155         [&Objs](std::unique_ptr<llvm::MemoryBuffer> MB) {
156           Objs.push_back(std::move(MB));
157         });
158     JIT = &J;
159     return llvm::Error::success();
160   });
161 
162   llvm::Error ErrOut = llvm::Error::success();
163   CustomJBInterpreter Interp(std::move(CI), ErrOut, std::move(JB));
164   cantFail(std::move(ErrOut));
165 
166   EXPECT_EQ(0U, Objs.size());
167   cantFail(Interp.ParseAndExecute("int a = 1;"));
168   ASSERT_NE(JIT, nullptr); // But it is, because JBCreator was never called
169   ExecutorAddr Addr = cantFail(JIT->lookup("a"));
170   EXPECT_NE(0U, Addr.getValue());
171   EXPECT_EQ(1U, Objs.size());
172 }
173 
174 } // end anonymous namespace
175