1 //===- unittests/Interpreter/InterpreterExtensionsTest.cpp ----------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Unit tests for Clang's Interpreter library.
11 //===----------------------------------------------------------------------===//
13 #include "InterpreterTestFixture.h"
15 #include "clang/Interpreter/Interpreter.h"
17 #include "clang/AST/Expr.h"
18 #include "clang/Frontend/CompilerInstance.h"
19 #include "clang/Sema/Lookup.h"
20 #include "clang/Sema/Sema.h"
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"
28 #include "gmock/gmock.h"
29 #include "gtest/gtest.h"
31 #include <system_error>
33 #if defined(_AIX) || defined(__MVS__)
34 #define CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
37 using namespace clang
;
40 class InterpreterExtensionsTest
: public InterpreterTestBase
{
42 void SetUp() override
{
43 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
48 static void SetUpTestSuite() {
49 llvm::InitializeAllTargets();
50 llvm::InitializeAllTargetInfos();
51 llvm::InitializeAllTargetMCs();
52 llvm::InitializeAllAsmPrinters();
56 // Some tests require a arm-registered-target
57 static bool IsARMTargetRegistered() {
59 TT
.setArch(llvm::Triple::arm
);
60 TT
.setVendor(llvm::Triple::UnknownVendor
);
61 TT
.setOS(llvm::Triple::UnknownOS
);
63 std::string UnusedErr
;
64 return llvm::TargetRegistry::lookupTarget(TT
.str(), UnusedErr
);
68 struct OutOfProcInterpreter
: public Interpreter
{
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
)) {}
77 TEST_F(InterpreterExtensionsTest
, FindRuntimeInterface
) {
78 if (!HostSupportsJIT())
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"));
94 // Make sure no clang::Value logic is attached by the Interpreter.
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());
102 class CustomJBInterpreter
: public Interpreter
{
103 using CustomJITBuilderCreatorFunction
=
104 std::function
<llvm::Expected
<std::unique_ptr
<llvm::orc::LLJITBuilder
>>()>;
105 CustomJITBuilderCreatorFunction JBCreator
= nullptr;
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
)) {}
112 ~CustomJBInterpreter() override
{
113 // Skip cleanUp() because it would trigger LLJIT default dtors
114 Interpreter::ResetExecutor();
117 llvm::Error
CreateExecutor() { return Interpreter::CreateExecutor(); }
120 TEST_F(InterpreterExtensionsTest
, DefaultCrossJIT
) {
121 if (!IsARMTargetRegistered())
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
));
132 TEST_F(InterpreterExtensionsTest
, CustomCrossJIT
) {
133 if (!IsARMTargetRegistered())
136 std::string TargetTriple
= "armv6-none-eabi";
138 IncrementalCompilerBuilder CB
;
139 CB
.SetTargetTriple(TargetTriple
);
140 auto CI
= cantFail(CB
.CreateCpp());
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");
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
));
159 return llvm::Error::success();
162 llvm::Error ErrOut
= llvm::Error::success();
163 CustomJBInterpreter
Interp(std::move(CI
), ErrOut
, std::move(JB
));
164 cantFail(std::move(ErrOut
));
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());
174 } // end anonymous namespace