1 //===- MCJITTest.cpp - Unit tests for the MCJIT ---------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This test suite verifies basic MCJIT functionality when invoked form the C
13 //===----------------------------------------------------------------------===//
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/Scalar.h"
20 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
21 #include "llvm/Support/Host.h"
22 #include "MCJITTestAPICommon.h"
23 #include "gtest/gtest.h"
27 static bool didCallAllocateCodeSection;
29 static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
32 const char *sectionName) {
33 didCallAllocateCodeSection = true;
34 return static_cast<SectionMemoryManager*>(object)->allocateCodeSection(
35 size, alignment, sectionID, sectionName);
38 static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size,
41 const char *sectionName,
42 LLVMBool isReadOnly) {
43 return static_cast<SectionMemoryManager*>(object)->allocateDataSection(
44 size, alignment, sectionID, sectionName, isReadOnly);
47 static LLVMBool roundTripFinalizeMemory(void *object, char **errMsg) {
48 std::string errMsgString;
50 static_cast<SectionMemoryManager*>(object)->finalizeMemory(&errMsgString);
52 *errMsg = LLVMCreateMessage(errMsgString.c_str());
58 static void roundTripDestroy(void *object) {
59 delete static_cast<SectionMemoryManager*>(object);
62 class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
65 // The architectures below are known to be compatible with MCJIT as they
66 // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
68 SupportedArchs.push_back(Triple::aarch64);
69 SupportedArchs.push_back(Triple::arm);
70 SupportedArchs.push_back(Triple::mips);
71 SupportedArchs.push_back(Triple::x86);
72 SupportedArchs.push_back(Triple::x86_64);
74 // Some architectures have sub-architectures in which tests will fail, like
75 // ARM. These two vectors will define if they do have sub-archs (to avoid
76 // extra work for those who don't), and if so, if they are listed to work
77 HasSubArchs.push_back(Triple::arm);
78 SupportedSubArchs.push_back("armv6");
79 SupportedSubArchs.push_back("armv7");
81 // The operating systems below are known to be sufficiently incompatible
82 // that they will fail the MCJIT C API tests.
83 UnsupportedOSs.push_back(Triple::Cygwin);
88 virtual void TearDown() {
90 LLVMDisposeExecutionEngine(Engine);
92 LLVMDisposeModule(Module);
95 void buildSimpleFunction() {
96 Module = LLVMModuleCreateWithName("simple_module");
98 LLVMSetTarget(Module, HostTriple.c_str());
100 Function = LLVMAddFunction(
101 Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
102 LLVMSetFunctionCallConv(Function, LLVMCCallConv);
104 LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
105 LLVMBuilderRef builder = LLVMCreateBuilder();
106 LLVMPositionBuilderAtEnd(builder, entry);
107 LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
109 LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
110 LLVMDisposeMessage(Error);
112 LLVMDisposeBuilder(builder);
115 void buildMCJITOptions() {
116 LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
117 Options.OptLevel = 2;
119 // Just ensure that this field still exists.
120 Options.NoFramePointerElim = false;
123 void useRoundTripSectionMemoryManager() {
124 Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
125 new SectionMemoryManager(),
126 roundTripAllocateCodeSection,
127 roundTripAllocateDataSection,
128 roundTripFinalizeMemory,
132 void buildMCJITEngine() {
134 0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
135 sizeof(Options), &Error));
138 void buildAndRunPasses() {
139 LLVMPassManagerRef pass = LLVMCreatePassManager();
140 LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), pass);
141 LLVMAddConstantPropagationPass(pass);
142 LLVMAddInstructionCombiningPass(pass);
143 LLVMRunPassManager(pass, Module);
144 LLVMDisposePassManager(pass);
147 LLVMModuleRef Module;
148 LLVMValueRef Function;
149 LLVMMCJITCompilerOptions Options;
150 LLVMExecutionEngineRef Engine;
154 void MCJITCAPITest::SetUp() {
155 didCallAllocateCodeSection = false;
162 TEST_F(MCJITCAPITest, simple_function) {
163 SKIP_UNSUPPORTED_PLATFORM;
165 buildSimpleFunction();
174 functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
176 EXPECT_EQ(42, functionPointer.usable());
179 TEST_F(MCJITCAPITest, custom_memory_manager) {
180 SKIP_UNSUPPORTED_PLATFORM;
182 buildSimpleFunction();
184 useRoundTripSectionMemoryManager();
192 functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
194 EXPECT_EQ(42, functionPointer.usable());
195 EXPECT_TRUE(didCallAllocateCodeSection);