[docs] Fix build-docs.sh
[llvm-project.git] / llvm / unittests / ExecutionEngine / MCJIT / MCJITCAPITest.cpp
blob085e8f801db4a4d2229f416ccffca8068c860676
1 //===- MCJITTest.cpp - Unit tests for the MCJIT -----------------*- C++ -*-===//
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 // This test suite verifies basic MCJIT functionality when invoked form the C
10 // API.
12 //===----------------------------------------------------------------------===//
14 #include "MCJITTestAPICommon.h"
15 #include "llvm-c/Analysis.h"
16 #include "llvm-c/Core.h"
17 #include "llvm-c/ExecutionEngine.h"
18 #include "llvm-c/Target.h"
19 #include "llvm-c/Transforms/PassManagerBuilder.h"
20 #include "llvm-c/Transforms/Scalar.h"
21 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/Host.h"
24 #include "gtest/gtest.h"
26 using namespace llvm;
28 static bool didCallAllocateCodeSection;
29 static bool didAllocateCompactUnwindSection;
30 static bool didCallYield;
32 static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
33 unsigned alignment,
34 unsigned sectionID,
35 const char *sectionName) {
36 didCallAllocateCodeSection = true;
37 return static_cast<SectionMemoryManager*>(object)->allocateCodeSection(
38 size, alignment, sectionID, sectionName);
41 static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size,
42 unsigned alignment,
43 unsigned sectionID,
44 const char *sectionName,
45 LLVMBool isReadOnly) {
46 if (!strcmp(sectionName, "__compact_unwind"))
47 didAllocateCompactUnwindSection = true;
48 return static_cast<SectionMemoryManager*>(object)->allocateDataSection(
49 size, alignment, sectionID, sectionName, isReadOnly);
52 static LLVMBool roundTripFinalizeMemory(void *object, char **errMsg) {
53 std::string errMsgString;
54 bool result =
55 static_cast<SectionMemoryManager*>(object)->finalizeMemory(&errMsgString);
56 if (result) {
57 *errMsg = LLVMCreateMessage(errMsgString.c_str());
58 return 1;
60 return 0;
63 static void roundTripDestroy(void *object) {
64 delete static_cast<SectionMemoryManager*>(object);
67 static void yield(LLVMContextRef, void *) {
68 didCallYield = true;
71 namespace {
73 // memory manager to test reserve allocation space callback
74 class TestReserveAllocationSpaceMemoryManager: public SectionMemoryManager {
75 public:
76 uintptr_t ReservedCodeSize;
77 uintptr_t UsedCodeSize;
78 uintptr_t ReservedDataSizeRO;
79 uintptr_t UsedDataSizeRO;
80 uintptr_t ReservedDataSizeRW;
81 uintptr_t UsedDataSizeRW;
83 TestReserveAllocationSpaceMemoryManager() :
84 ReservedCodeSize(0), UsedCodeSize(0), ReservedDataSizeRO(0),
85 UsedDataSizeRO(0), ReservedDataSizeRW(0), UsedDataSizeRW(0) {
88 bool needsToReserveAllocationSpace() override { return true; }
90 void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
91 uintptr_t DataSizeRO, uint32_t RODataAlign,
92 uintptr_t DataSizeRW,
93 uint32_t RWDataAlign) override {
94 ReservedCodeSize = CodeSize;
95 ReservedDataSizeRO = DataSizeRO;
96 ReservedDataSizeRW = DataSizeRW;
99 void useSpace(uintptr_t* UsedSize, uintptr_t Size, unsigned Alignment) {
100 uintptr_t AlignedSize = (Size + Alignment - 1) / Alignment * Alignment;
101 uintptr_t AlignedBegin = (*UsedSize + Alignment - 1) / Alignment * Alignment;
102 *UsedSize = AlignedBegin + AlignedSize;
105 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
106 unsigned SectionID, StringRef SectionName,
107 bool IsReadOnly) override {
108 useSpace(IsReadOnly ? &UsedDataSizeRO : &UsedDataSizeRW, Size, Alignment);
109 return SectionMemoryManager::allocateDataSection(Size, Alignment,
110 SectionID, SectionName, IsReadOnly);
113 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
114 unsigned SectionID,
115 StringRef SectionName) override {
116 useSpace(&UsedCodeSize, Size, Alignment);
117 return SectionMemoryManager::allocateCodeSection(Size, Alignment,
118 SectionID, SectionName);
122 class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
123 protected:
124 MCJITCAPITest() {
125 // The architectures below are known to be compatible with MCJIT as they
126 // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
127 // kept in sync.
128 SupportedArchs.push_back(Triple::aarch64);
129 SupportedArchs.push_back(Triple::arm);
130 SupportedArchs.push_back(Triple::mips);
131 SupportedArchs.push_back(Triple::mips64);
132 SupportedArchs.push_back(Triple::mips64el);
133 SupportedArchs.push_back(Triple::x86);
134 SupportedArchs.push_back(Triple::x86_64);
136 // Some architectures have sub-architectures in which tests will fail, like
137 // ARM. These two vectors will define if they do have sub-archs (to avoid
138 // extra work for those who don't), and if so, if they are listed to work
139 HasSubArchs.push_back(Triple::arm);
140 SupportedSubArchs.push_back("armv6");
141 SupportedSubArchs.push_back("armv7");
143 // The operating systems below are known to be sufficiently incompatible
144 // that they will fail the MCJIT C API tests.
145 UnsupportedEnvironments.push_back(Triple::Cygnus);
148 void SetUp() override {
149 didCallAllocateCodeSection = false;
150 didAllocateCompactUnwindSection = false;
151 didCallYield = false;
152 Module = nullptr;
153 Function = nullptr;
154 Engine = nullptr;
155 Error = nullptr;
158 void TearDown() override {
159 if (Engine)
160 LLVMDisposeExecutionEngine(Engine);
161 else if (Module)
162 LLVMDisposeModule(Module);
165 void buildSimpleFunction() {
166 Module = LLVMModuleCreateWithName("simple_module");
168 LLVMSetTarget(Module, HostTriple.c_str());
170 Function = LLVMAddFunction(Module, "simple_function",
171 LLVMFunctionType(LLVMInt32Type(), nullptr,0, 0));
172 LLVMSetFunctionCallConv(Function, LLVMCCallConv);
174 LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
175 LLVMBuilderRef builder = LLVMCreateBuilder();
176 LLVMPositionBuilderAtEnd(builder, entry);
177 LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
179 LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
180 LLVMDisposeMessage(Error);
182 LLVMDisposeBuilder(builder);
185 void buildFunctionThatUsesStackmap() {
186 Module = LLVMModuleCreateWithName("simple_module");
188 LLVMSetTarget(Module, HostTriple.c_str());
190 LLVMTypeRef stackmapParamTypes[] = { LLVMInt64Type(), LLVMInt32Type() };
191 LLVMTypeRef stackmapTy =
192 LLVMFunctionType(LLVMVoidType(), stackmapParamTypes, 2, 1);
193 LLVMValueRef stackmap = LLVMAddFunction(
194 Module, "llvm.experimental.stackmap", stackmapTy);
195 LLVMSetLinkage(stackmap, LLVMExternalLinkage);
197 Function = LLVMAddFunction(Module, "simple_function",
198 LLVMFunctionType(LLVMInt32Type(), nullptr, 0, 0));
200 LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
201 LLVMBuilderRef builder = LLVMCreateBuilder();
202 LLVMPositionBuilderAtEnd(builder, entry);
203 LLVMValueRef stackmapArgs[] = {
204 LLVMConstInt(LLVMInt64Type(), 0, 0), LLVMConstInt(LLVMInt32Type(), 5, 0),
205 LLVMConstInt(LLVMInt32Type(), 42, 0)
207 LLVMBuildCall2(builder, stackmapTy, stackmap, stackmapArgs, 3, "");
208 LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
210 LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
211 LLVMDisposeMessage(Error);
213 LLVMDisposeBuilder(builder);
216 void buildModuleWithCodeAndData() {
217 Module = LLVMModuleCreateWithName("simple_module");
219 LLVMSetTarget(Module, HostTriple.c_str());
221 // build a global int32 variable initialized to 42.
222 LLVMValueRef GlobalVar = LLVMAddGlobal(Module, LLVMInt32Type(), "intVal");
223 LLVMSetInitializer(GlobalVar, LLVMConstInt(LLVMInt32Type(), 42, 0));
226 Function = LLVMAddFunction(Module, "getGlobal",
227 LLVMFunctionType(LLVMInt32Type(), nullptr, 0, 0));
228 LLVMSetFunctionCallConv(Function, LLVMCCallConv);
230 LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function, "entry");
231 LLVMBuilderRef Builder = LLVMCreateBuilder();
232 LLVMPositionBuilderAtEnd(Builder, Entry);
234 LLVMValueRef IntVal =
235 LLVMBuildLoad2(Builder, LLVMInt32Type(), GlobalVar, "intVal");
236 LLVMBuildRet(Builder, IntVal);
238 LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
239 LLVMDisposeMessage(Error);
241 LLVMDisposeBuilder(Builder);
245 LLVMTypeRef ParamTypes[] = { LLVMInt32Type() };
246 Function2 = LLVMAddFunction(
247 Module, "setGlobal", LLVMFunctionType(LLVMVoidType(), ParamTypes, 1, 0));
248 LLVMSetFunctionCallConv(Function2, LLVMCCallConv);
250 LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function2, "entry");
251 LLVMBuilderRef Builder = LLVMCreateBuilder();
252 LLVMPositionBuilderAtEnd(Builder, Entry);
254 LLVMValueRef Arg = LLVMGetParam(Function2, 0);
255 LLVMBuildStore(Builder, Arg, GlobalVar);
256 LLVMBuildRetVoid(Builder);
258 LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
259 LLVMDisposeMessage(Error);
261 LLVMDisposeBuilder(Builder);
265 void buildMCJITOptions() {
266 LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
267 Options.OptLevel = 2;
269 // Just ensure that this field still exists.
270 Options.NoFramePointerElim = false;
273 void useRoundTripSectionMemoryManager() {
274 Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
275 new SectionMemoryManager(),
276 roundTripAllocateCodeSection,
277 roundTripAllocateDataSection,
278 roundTripFinalizeMemory,
279 roundTripDestroy);
282 void buildMCJITEngine() {
283 ASSERT_EQ(
284 0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
285 sizeof(Options), &Error));
288 void buildAndRunPasses() {
289 LLVMPassManagerRef pass = LLVMCreatePassManager();
290 LLVMAddInstructionCombiningPass(pass);
291 LLVMRunPassManager(pass, Module);
292 LLVMDisposePassManager(pass);
295 void buildAndRunOptPasses() {
296 LLVMPassManagerBuilderRef passBuilder;
298 passBuilder = LLVMPassManagerBuilderCreate();
299 LLVMPassManagerBuilderSetOptLevel(passBuilder, 2);
300 LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0);
302 LLVMPassManagerRef functionPasses =
303 LLVMCreateFunctionPassManagerForModule(Module);
304 LLVMPassManagerRef modulePasses =
305 LLVMCreatePassManager();
307 LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder,
308 functionPasses);
309 LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses);
311 LLVMPassManagerBuilderDispose(passBuilder);
313 LLVMInitializeFunctionPassManager(functionPasses);
314 for (LLVMValueRef value = LLVMGetFirstFunction(Module);
315 value; value = LLVMGetNextFunction(value))
316 LLVMRunFunctionPassManager(functionPasses, value);
317 LLVMFinalizeFunctionPassManager(functionPasses);
319 LLVMRunPassManager(modulePasses, Module);
321 LLVMDisposePassManager(functionPasses);
322 LLVMDisposePassManager(modulePasses);
325 LLVMModuleRef Module;
326 LLVMValueRef Function;
327 LLVMValueRef Function2;
328 LLVMMCJITCompilerOptions Options;
329 LLVMExecutionEngineRef Engine;
330 char *Error;
332 } // end anonymous namespace
334 TEST_F(MCJITCAPITest, simple_function) {
335 SKIP_UNSUPPORTED_PLATFORM;
337 buildSimpleFunction();
338 buildMCJITOptions();
339 buildMCJITEngine();
340 buildAndRunPasses();
342 auto *functionPointer = reinterpret_cast<int (*)()>(
343 reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(Engine, Function)));
345 EXPECT_EQ(42, functionPointer());
348 TEST_F(MCJITCAPITest, gva) {
349 SKIP_UNSUPPORTED_PLATFORM;
351 Module = LLVMModuleCreateWithName("simple_module");
352 LLVMSetTarget(Module, HostTriple.c_str());
353 LLVMValueRef GlobalVar = LLVMAddGlobal(Module, LLVMInt32Type(), "simple_value");
354 LLVMSetInitializer(GlobalVar, LLVMConstInt(LLVMInt32Type(), 42, 0));
356 buildMCJITOptions();
357 buildMCJITEngine();
358 buildAndRunPasses();
360 uint64_t raw = LLVMGetGlobalValueAddress(Engine, "simple_value");
361 int32_t *usable = (int32_t *) raw;
363 EXPECT_EQ(42, *usable);
366 TEST_F(MCJITCAPITest, gfa) {
367 SKIP_UNSUPPORTED_PLATFORM;
369 buildSimpleFunction();
370 buildMCJITOptions();
371 buildMCJITEngine();
372 buildAndRunPasses();
374 uint64_t raw = LLVMGetFunctionAddress(Engine, "simple_function");
375 int (*usable)() = (int (*)()) raw;
377 EXPECT_EQ(42, usable());
380 TEST_F(MCJITCAPITest, custom_memory_manager) {
381 SKIP_UNSUPPORTED_PLATFORM;
383 buildSimpleFunction();
384 buildMCJITOptions();
385 useRoundTripSectionMemoryManager();
386 buildMCJITEngine();
387 buildAndRunPasses();
389 auto *functionPointer = reinterpret_cast<int (*)()>(
390 reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(Engine, Function)));
392 EXPECT_EQ(42, functionPointer());
393 EXPECT_TRUE(didCallAllocateCodeSection);
396 TEST_F(MCJITCAPITest, stackmap_creates_compact_unwind_on_darwin) {
397 SKIP_UNSUPPORTED_PLATFORM;
399 // This test is also not supported on non-x86 platforms.
400 if (Triple(HostTriple).getArch() != Triple::x86_64)
401 return;
403 buildFunctionThatUsesStackmap();
404 buildMCJITOptions();
405 useRoundTripSectionMemoryManager();
406 buildMCJITEngine();
407 buildAndRunOptPasses();
409 auto *functionPointer = reinterpret_cast<int (*)()>(
410 reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(Engine, Function)));
412 EXPECT_EQ(42, functionPointer());
413 EXPECT_TRUE(didCallAllocateCodeSection);
415 // Up to this point, the test is specific only to X86-64. But this next
416 // expectation is only valid on Darwin because it assumes that unwind
417 // data is made available only through compact_unwind. It would be
418 // worthwhile to extend this to handle non-Darwin platforms, in which
419 // case you'd want to look for an eh_frame or something.
421 // FIXME: Currently, MCJIT relies on a configure-time check to determine which
422 // sections to emit. The JIT client should have runtime control over this.
423 EXPECT_TRUE(
424 Triple(HostTriple).getOS() != Triple::Darwin ||
425 Triple(HostTriple).isMacOSXVersionLT(10, 7) ||
426 didAllocateCompactUnwindSection);
429 #if defined(__APPLE__) && defined(__aarch64__)
430 // FIXME: Figure out why this fails on mac/arm, PR46647
431 #define MAYBE_reserve_allocation_space DISABLED_reserve_allocation_space
432 #else
433 #define MAYBE_reserve_allocation_space reserve_allocation_space
434 #endif
435 TEST_F(MCJITCAPITest, MAYBE_reserve_allocation_space) {
436 SKIP_UNSUPPORTED_PLATFORM;
438 TestReserveAllocationSpaceMemoryManager* MM = new TestReserveAllocationSpaceMemoryManager();
440 buildModuleWithCodeAndData();
441 buildMCJITOptions();
442 Options.MCJMM = wrap(MM);
443 buildMCJITEngine();
444 buildAndRunPasses();
446 auto GetGlobalFct = reinterpret_cast<int (*)()>(
447 reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(Engine, Function)));
449 auto SetGlobalFct = reinterpret_cast<void (*)(int)>(
450 reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(Engine, Function2)));
452 SetGlobalFct(789);
453 EXPECT_EQ(789, GetGlobalFct());
454 EXPECT_LE(MM->UsedCodeSize, MM->ReservedCodeSize);
455 EXPECT_LE(MM->UsedDataSizeRO, MM->ReservedDataSizeRO);
456 EXPECT_LE(MM->UsedDataSizeRW, MM->ReservedDataSizeRW);
457 EXPECT_TRUE(MM->UsedCodeSize > 0);
458 EXPECT_TRUE(MM->UsedDataSizeRW > 0);
461 TEST_F(MCJITCAPITest, yield) {
462 SKIP_UNSUPPORTED_PLATFORM;
464 buildSimpleFunction();
465 buildMCJITOptions();
466 buildMCJITEngine();
467 LLVMContextRef C = LLVMGetGlobalContext();
468 LLVMContextSetYieldCallback(C, yield, nullptr);
469 buildAndRunPasses();
471 auto *functionPointer = reinterpret_cast<int (*)()>(
472 reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(Engine, Function)));
474 EXPECT_EQ(42, functionPointer());
475 EXPECT_TRUE(didCallYield);
478 static int localTestFunc() {
479 return 42;
482 TEST_F(MCJITCAPITest, addGlobalMapping) {
483 SKIP_UNSUPPORTED_PLATFORM;
485 Module = LLVMModuleCreateWithName("testModule");
486 LLVMSetTarget(Module, HostTriple.c_str());
487 LLVMTypeRef FunctionType = LLVMFunctionType(LLVMInt32Type(), nullptr, 0, 0);
488 LLVMValueRef MappedFn = LLVMAddFunction(Module, "mapped_fn", FunctionType);
490 Function = LLVMAddFunction(Module, "test_fn", FunctionType);
491 LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function, "");
492 LLVMBuilderRef Builder = LLVMCreateBuilder();
493 LLVMPositionBuilderAtEnd(Builder, Entry);
494 LLVMValueRef RetVal =
495 LLVMBuildCall2(Builder, FunctionType, MappedFn, nullptr, 0, "");
496 LLVMBuildRet(Builder, RetVal);
497 LLVMDisposeBuilder(Builder);
499 LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
500 LLVMDisposeMessage(Error);
502 buildMCJITOptions();
503 buildMCJITEngine();
505 LLVMAddGlobalMapping(
506 Engine, MappedFn,
507 reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(&localTestFunc)));
509 buildAndRunPasses();
511 uint64_t raw = LLVMGetFunctionAddress(Engine, "test_fn");
512 int (*usable)() = (int (*)()) raw;
514 EXPECT_EQ(42, usable());