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
37using namespace clang;
38namespace {
39
40class InterpreterExtensionsTest : public InterpreterTestBase {
41protected:
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
55public:
56 // Some tests require a arm-registered-target
57 static bool IsARMTargetRegistered() {
58 llvm::Triple TT;
59 TT.setArch(Kind: 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(TheTriple: TT, Error&: 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 if (!HostSupportsJIT())
79 GTEST_SKIP();
80
81 clang::IncrementalCompilerBuilder CB;
82 llvm::Error ErrOut = llvm::Error::success();
83 auto CI = cantFail(ValOrErr: 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(Err: std::move(ErrOut));
90 cantFail(ValOrErr: I.Parse(Code: "int a = 1; a"));
91 cantFail(ValOrErr: I.Parse(Code: "int b = 2; b"));
92 cantFail(ValOrErr: I.Parse(Code: "int c = 3; c"));
93
94 // Make sure no clang::Value logic is attached by the Interpreter.
95 Value V1;
96 llvm::cantFail(Err: I.ParseAndExecute(Code: "int x = 42;"));
97 llvm::cantFail(Err: I.ParseAndExecute(Code: "x", V: &V1));
98 EXPECT_FALSE(V1.isValid());
99 EXPECT_FALSE(V1.hasValue());
100}
101
102class CustomJBInterpreter : public Interpreter {
103 using CustomJITBuilderCreatorFunction =
104 std::function<llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>()>;
105 CustomJITBuilderCreatorFunction JBCreator = nullptr;
106
107public:
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
120TEST_F(InterpreterExtensionsTest, DefaultCrossJIT) {
121 if (!IsARMTargetRegistered())
122 GTEST_SKIP();
123
124 IncrementalCompilerBuilder CB;
125 CB.SetTargetTriple("armv6-none-eabi");
126 auto CI = cantFail(ValOrErr: CB.CreateCpp());
127 llvm::Error ErrOut = llvm::Error::success();
128 CustomJBInterpreter Interp(std::move(CI), ErrOut, nullptr);
129 cantFail(Err: std::move(ErrOut));
130}
131
132TEST_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(ValOrErr: 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>(Val: &ObjLayer);
154 JITLinkObjLayer->setReturnObjectBuffer(
155 [&Objs](std::unique_ptr<llvm::MemoryBuffer> MB) {
156 Objs.push_back(x: 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(Err: std::move(ErrOut));
165
166 EXPECT_EQ(0U, Objs.size());
167 cantFail(Err: Interp.ParseAndExecute(Code: "int a = 1;"));
168 ASSERT_NE(JIT, nullptr); // But it is, because JBCreator was never called
169 ExecutorAddr Addr = cantFail(ValOrErr: JIT->lookup(UnmangledName: "a"));
170 EXPECT_NE(0U, Addr.getValue());
171 EXPECT_EQ(1U, Objs.size());
172}
173
174} // end anonymous namespace
175

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang/unittests/Interpreter/InterpreterExtensionsTest.cpp