blob: c434a7c0b25b149e121dd8d3bec8b31051143c42 [file] [log] [blame]
Andrew Kaylord2755af2013-04-29 17:49:40 +00001//===- MCJITTest.cpp - Unit tests for the MCJIT ---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This test suite verifies basic MCJIT functionality when invoked form the C
11// API.
12//
13//===----------------------------------------------------------------------===//
14
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"
Filip Pizlo52755c42013-05-21 20:00:56 +000020#include "llvm/ExecutionEngine/SectionMemoryManager.h"
Andrew Kaylord2755af2013-04-29 17:49:40 +000021#include "llvm/Support/Host.h"
22#include "MCJITTestAPICommon.h"
23#include "gtest/gtest.h"
24
25using namespace llvm;
26
Filip Pizlo52755c42013-05-21 20:00:56 +000027static bool didCallAllocateCodeSection;
28
29static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
30 unsigned alignment,
31 unsigned sectionID) {
32 didCallAllocateCodeSection = true;
33 return static_cast<SectionMemoryManager*>(object)->allocateCodeSection(
34 size, alignment, sectionID);
35}
36
37static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size,
38 unsigned alignment,
39 unsigned sectionID,
40 LLVMBool isReadOnly) {
41 return static_cast<SectionMemoryManager*>(object)->allocateDataSection(
42 size, alignment, sectionID, isReadOnly);
43}
44
45static LLVMBool roundTripFinalizeMemory(void *object, char **errMsg) {
46 std::string errMsgString;
47 bool result =
48 static_cast<SectionMemoryManager*>(object)->finalizeMemory(&errMsgString);
49 if (result) {
50 *errMsg = LLVMCreateMessage(errMsgString.c_str());
51 return 1;
52 }
53 return 0;
54}
55
56static void roundTripDestroy(void *object) {
57 delete static_cast<SectionMemoryManager*>(object);
58}
59
Andrew Kaylord2755af2013-04-29 17:49:40 +000060class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
61protected:
62 MCJITCAPITest() {
63 // The architectures below are known to be compatible with MCJIT as they
64 // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
65 // kept in sync.
Tim Northover233a4d72013-05-19 19:44:56 +000066 SupportedArchs.push_back(Triple::aarch64);
Andrew Kaylord2755af2013-04-29 17:49:40 +000067 SupportedArchs.push_back(Triple::arm);
68 SupportedArchs.push_back(Triple::mips);
69 SupportedArchs.push_back(Triple::x86);
70 SupportedArchs.push_back(Triple::x86_64);
71
Renato Golin4e4464b2013-05-19 20:10:10 +000072 // Some architectures have sub-architectures in which tests will fail, like
73 // ARM. These two vectors will define if they do have sub-archs (to avoid
74 // extra work for those who don't), and if so, if they are listed to work
75 HasSubArchs.push_back(Triple::arm);
76 SupportedSubArchs.push_back("armv6");
77 SupportedSubArchs.push_back("armv7");
78
Andrew Kaylord2755af2013-04-29 17:49:40 +000079 // The operating systems below are known to be sufficiently incompatible
80 // that they will fail the MCJIT C API tests.
81 UnsupportedOSs.push_back(Triple::Cygwin);
82 }
Filip Pizlo52755c42013-05-21 20:00:56 +000083
84 virtual void SetUp() {
85 didCallAllocateCodeSection = false;
86 Module = 0;
87 Function = 0;
88 Engine = 0;
89 Error = 0;
90 }
91
92 virtual void TearDown() {
93 if (Engine)
94 LLVMDisposeExecutionEngine(Engine);
95 else if (Module)
96 LLVMDisposeModule(Module);
97 }
98
99 void buildSimpleFunction() {
100 Module = LLVMModuleCreateWithName("simple_module");
101
102 LLVMSetTarget(Module, HostTriple.c_str());
103
104 Function = LLVMAddFunction(
105 Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
106 LLVMSetFunctionCallConv(Function, LLVMCCallConv);
107
108 LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
109 LLVMBuilderRef builder = LLVMCreateBuilder();
110 LLVMPositionBuilderAtEnd(builder, entry);
111 LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
112
113 LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
114 LLVMDisposeMessage(Error);
115
116 LLVMDisposeBuilder(builder);
117 }
118
119 void buildMCJITOptions() {
120 LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
121 Options.OptLevel = 2;
122
123 // Just ensure that this field still exists.
124 Options.NoFramePointerElim = false;
125 }
126
127 void useRoundTripSectionMemoryManager() {
128 Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
129 new SectionMemoryManager(),
130 roundTripAllocateCodeSection,
131 roundTripAllocateDataSection,
132 roundTripFinalizeMemory,
133 roundTripDestroy);
134 }
135
136 void buildMCJITEngine() {
137 ASSERT_EQ(
138 0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
139 sizeof(Options), &Error));
140 }
141
142 void buildAndRunPasses() {
143 LLVMPassManagerRef pass = LLVMCreatePassManager();
144 LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), pass);
145 LLVMAddConstantPropagationPass(pass);
146 LLVMAddInstructionCombiningPass(pass);
147 LLVMRunPassManager(pass, Module);
148 LLVMDisposePassManager(pass);
149 }
150
151 LLVMModuleRef Module;
152 LLVMValueRef Function;
153 LLVMMCJITCompilerOptions Options;
154 LLVMExecutionEngineRef Engine;
155 char *Error;
Andrew Kaylord2755af2013-04-29 17:49:40 +0000156};
157
158TEST_F(MCJITCAPITest, simple_function) {
159 SKIP_UNSUPPORTED_PLATFORM;
160
Filip Pizlo52755c42013-05-21 20:00:56 +0000161 buildSimpleFunction();
162 buildMCJITOptions();
163 buildMCJITEngine();
164 buildAndRunPasses();
Andrew Kaylord2755af2013-04-29 17:49:40 +0000165
166 union {
167 void *raw;
168 int (*usable)();
169 } functionPointer;
Filip Pizlo52755c42013-05-21 20:00:56 +0000170 functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
Andrew Kaylord2755af2013-04-29 17:49:40 +0000171
172 EXPECT_EQ(42, functionPointer.usable());
Andrew Kaylord2755af2013-04-29 17:49:40 +0000173}
174
Filip Pizlo52755c42013-05-21 20:00:56 +0000175TEST_F(MCJITCAPITest, custom_memory_manager) {
176 SKIP_UNSUPPORTED_PLATFORM;
177
178 buildSimpleFunction();
179 buildMCJITOptions();
180 useRoundTripSectionMemoryManager();
181 buildMCJITEngine();
182 buildAndRunPasses();
183
184 union {
185 void *raw;
186 int (*usable)();
187 } functionPointer;
188 functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
189
190 EXPECT_EQ(42, functionPointer.usable());
191 EXPECT_TRUE(didCallAllocateCodeSection);
192}