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);
86 virtual void SetUp() {
87 didCallAllocateCodeSection = false;
94 virtual void TearDown() {
96 LLVMDisposeExecutionEngine(Engine);
98 LLVMDisposeModule(Module);
101 void buildSimpleFunction() {
102 Module = LLVMModuleCreateWithName("simple_module");
104 LLVMSetTarget(Module, HostTriple.c_str());
106 Function = LLVMAddFunction(
107 Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
108 LLVMSetFunctionCallConv(Function, LLVMCCallConv);
110 LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
111 LLVMBuilderRef builder = LLVMCreateBuilder();
112 LLVMPositionBuilderAtEnd(builder, entry);
113 LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
115 LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
116 LLVMDisposeMessage(Error);
118 LLVMDisposeBuilder(builder);
121 void buildMCJITOptions() {
122 LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
123 Options.OptLevel = 2;
125 // Just ensure that this field still exists.
126 Options.NoFramePointerElim = false;
129 void useRoundTripSectionMemoryManager() {
130 Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
131 new SectionMemoryManager(),
132 roundTripAllocateCodeSection,
133 roundTripAllocateDataSection,
134 roundTripFinalizeMemory,
138 void buildMCJITEngine() {
140 0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
141 sizeof(Options), &Error));
144 void buildAndRunPasses() {
145 LLVMPassManagerRef pass = LLVMCreatePassManager();
146 LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), pass);
147 LLVMAddConstantPropagationPass(pass);
148 LLVMAddInstructionCombiningPass(pass);
149 LLVMRunPassManager(pass, Module);
150 LLVMDisposePassManager(pass);
153 LLVMModuleRef Module;
154 LLVMValueRef Function;
155 LLVMMCJITCompilerOptions Options;
156 LLVMExecutionEngineRef Engine;
160 TEST_F(MCJITCAPITest, simple_function) {
161 SKIP_UNSUPPORTED_PLATFORM;
163 buildSimpleFunction();
172 functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
174 EXPECT_EQ(42, functionPointer.usable());
177 TEST_F(MCJITCAPITest, custom_memory_manager) {
178 SKIP_UNSUPPORTED_PLATFORM;
180 buildSimpleFunction();
182 useRoundTripSectionMemoryManager();
190 functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
192 EXPECT_EQ(42, functionPointer.usable());
193 EXPECT_TRUE(didCallAllocateCodeSection);