blob: e4197ddced618d8954b662d30b9cee6d3275232c [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 Pizlo6cfed362013-05-22 02:46:43 +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 Pizlo6cfed362013-05-22 02:46:43 +000027static bool didCallAllocateCodeSection;
28
29static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
30 unsigned alignment,
Filip Pizlo6eb43d22013-10-02 00:59:25 +000031 unsigned sectionID,
32 const char *sectionName) {
Filip Pizlo6cfed362013-05-22 02:46:43 +000033 didCallAllocateCodeSection = true;
34 return static_cast<SectionMemoryManager*>(object)->allocateCodeSection(
Filip Pizlo6eb43d22013-10-02 00:59:25 +000035 size, alignment, sectionID, sectionName);
Filip Pizlo6cfed362013-05-22 02:46:43 +000036}
37
38static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size,
39 unsigned alignment,
40 unsigned sectionID,
Filip Pizlo6eb43d22013-10-02 00:59:25 +000041 const char *sectionName,
Filip Pizlo6cfed362013-05-22 02:46:43 +000042 LLVMBool isReadOnly) {
43 return static_cast<SectionMemoryManager*>(object)->allocateDataSection(
Filip Pizlo6eb43d22013-10-02 00:59:25 +000044 size, alignment, sectionID, sectionName, isReadOnly);
Filip Pizlo6cfed362013-05-22 02:46:43 +000045}
46
47static LLVMBool roundTripFinalizeMemory(void *object, char **errMsg) {
48 std::string errMsgString;
49 bool result =
50 static_cast<SectionMemoryManager*>(object)->finalizeMemory(&errMsgString);
51 if (result) {
52 *errMsg = LLVMCreateMessage(errMsgString.c_str());
53 return 1;
54 }
55 return 0;
56}
57
58static void roundTripDestroy(void *object) {
59 delete static_cast<SectionMemoryManager*>(object);
60}
61
Andrew Kaylord2755af2013-04-29 17:49:40 +000062class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
63protected:
64 MCJITCAPITest() {
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
67 // kept in sync.
Tim Northover233a4d72013-05-19 19:44:56 +000068 SupportedArchs.push_back(Triple::aarch64);
Andrew Kaylord2755af2013-04-29 17:49:40 +000069 SupportedArchs.push_back(Triple::arm);
70 SupportedArchs.push_back(Triple::mips);
71 SupportedArchs.push_back(Triple::x86);
72 SupportedArchs.push_back(Triple::x86_64);
73
Renato Golin4e4464b2013-05-19 20:10:10 +000074 // 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");
80
Andrew Kaylord2755af2013-04-29 17:49:40 +000081 // 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);
84 }
Filip Pizlo6cfed362013-05-22 02:46:43 +000085
86 virtual void SetUp() {
87 didCallAllocateCodeSection = false;
88 Module = 0;
89 Function = 0;
90 Engine = 0;
91 Error = 0;
92 }
93
94 virtual void TearDown() {
95 if (Engine)
96 LLVMDisposeExecutionEngine(Engine);
97 else if (Module)
98 LLVMDisposeModule(Module);
99 }
100
101 void buildSimpleFunction() {
102 Module = LLVMModuleCreateWithName("simple_module");
103
104 LLVMSetTarget(Module, HostTriple.c_str());
105
106 Function = LLVMAddFunction(
107 Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
108 LLVMSetFunctionCallConv(Function, LLVMCCallConv);
109
110 LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
111 LLVMBuilderRef builder = LLVMCreateBuilder();
112 LLVMPositionBuilderAtEnd(builder, entry);
113 LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
114
115 LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
116 LLVMDisposeMessage(Error);
117
118 LLVMDisposeBuilder(builder);
119 }
120
121 void buildMCJITOptions() {
122 LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
123 Options.OptLevel = 2;
124
125 // Just ensure that this field still exists.
126 Options.NoFramePointerElim = false;
127 }
128
129 void useRoundTripSectionMemoryManager() {
130 Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
131 new SectionMemoryManager(),
132 roundTripAllocateCodeSection,
133 roundTripAllocateDataSection,
134 roundTripFinalizeMemory,
135 roundTripDestroy);
136 }
137
138 void buildMCJITEngine() {
139 ASSERT_EQ(
140 0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
141 sizeof(Options), &Error));
142 }
143
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);
151 }
152
153 LLVMModuleRef Module;
154 LLVMValueRef Function;
155 LLVMMCJITCompilerOptions Options;
156 LLVMExecutionEngineRef Engine;
157 char *Error;
Andrew Kaylord2755af2013-04-29 17:49:40 +0000158};
159
160TEST_F(MCJITCAPITest, simple_function) {
161 SKIP_UNSUPPORTED_PLATFORM;
162
Filip Pizlo6cfed362013-05-22 02:46:43 +0000163 buildSimpleFunction();
164 buildMCJITOptions();
165 buildMCJITEngine();
166 buildAndRunPasses();
Andrew Kaylord2755af2013-04-29 17:49:40 +0000167
168 union {
169 void *raw;
170 int (*usable)();
171 } functionPointer;
Filip Pizlo6cfed362013-05-22 02:46:43 +0000172 functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
Andrew Kaylord2755af2013-04-29 17:49:40 +0000173
174 EXPECT_EQ(42, functionPointer.usable());
Andrew Kaylord2755af2013-04-29 17:49:40 +0000175}
176
Filip Pizlo6cfed362013-05-22 02:46:43 +0000177TEST_F(MCJITCAPITest, custom_memory_manager) {
178 SKIP_UNSUPPORTED_PLATFORM;
179
180 buildSimpleFunction();
181 buildMCJITOptions();
182 useRoundTripSectionMemoryManager();
183 buildMCJITEngine();
184 buildAndRunPasses();
185
186 union {
187 void *raw;
188 int (*usable)();
189 } functionPointer;
190 functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
191
192 EXPECT_EQ(42, functionPointer.usable());
193 EXPECT_TRUE(didCallAllocateCodeSection);
194}