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