[CMake] Update LLVM_LINK_COMPONENTS for each CMakeLists.txt.
[oota-llvm.git] / unittests / ExecutionEngine / MCJIT / MCJITCAPITest.cpp
1 //===- 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"
20 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
21 #include "llvm/Support/Host.h"
22 #include "MCJITTestAPICommon.h"
23 #include "gtest/gtest.h"
24
25 using namespace llvm;
26
27 static bool didCallAllocateCodeSection;
28
29 static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
30                                              unsigned alignment,
31                                              unsigned sectionID,
32                                              const char *sectionName) {
33   didCallAllocateCodeSection = true;
34   return static_cast<SectionMemoryManager*>(object)->allocateCodeSection(
35     size, alignment, sectionID, sectionName);
36 }
37
38 static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size,
39                                              unsigned alignment,
40                                              unsigned sectionID,
41                                              const char *sectionName,
42                                              LLVMBool isReadOnly) {
43   return static_cast<SectionMemoryManager*>(object)->allocateDataSection(
44     size, alignment, sectionID, sectionName, isReadOnly);
45 }
46
47 static 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
58 static void roundTripDestroy(void *object) {
59   delete static_cast<SectionMemoryManager*>(object);
60 }
61
62 namespace {
63 class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
64 protected:
65   MCJITCAPITest() {
66     // The architectures below are known to be compatible with MCJIT as they
67     // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
68     // kept in sync.
69     SupportedArchs.push_back(Triple::aarch64);
70     SupportedArchs.push_back(Triple::arm);
71     SupportedArchs.push_back(Triple::mips);
72     SupportedArchs.push_back(Triple::x86);
73     SupportedArchs.push_back(Triple::x86_64);
74
75     // Some architectures have sub-architectures in which tests will fail, like
76     // ARM. These two vectors will define if they do have sub-archs (to avoid
77     // extra work for those who don't), and if so, if they are listed to work
78     HasSubArchs.push_back(Triple::arm);
79     SupportedSubArchs.push_back("armv6");
80     SupportedSubArchs.push_back("armv7");
81
82     // The operating systems below are known to be sufficiently incompatible
83     // that they will fail the MCJIT C API tests.
84     UnsupportedOSs.push_back(Triple::Cygwin);
85   }
86   
87   virtual void SetUp() {
88     didCallAllocateCodeSection = false;
89     Module = 0;
90     Function = 0;
91     Engine = 0;
92     Error = 0;
93   }
94   
95   virtual void TearDown() {
96     if (Engine)
97       LLVMDisposeExecutionEngine(Engine);
98     else if (Module)
99       LLVMDisposeModule(Module);
100   }
101   
102   void buildSimpleFunction() {
103     Module = LLVMModuleCreateWithName("simple_module");
104     
105     LLVMSetTarget(Module, HostTriple.c_str());
106     
107     Function = LLVMAddFunction(
108       Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
109     LLVMSetFunctionCallConv(Function, LLVMCCallConv);
110     
111     LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
112     LLVMBuilderRef builder = LLVMCreateBuilder();
113     LLVMPositionBuilderAtEnd(builder, entry);
114     LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
115     
116     LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
117     LLVMDisposeMessage(Error);
118     
119     LLVMDisposeBuilder(builder);
120   }
121   
122   void buildMCJITOptions() {
123     LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
124     Options.OptLevel = 2;
125     
126     // Just ensure that this field still exists.
127     Options.NoFramePointerElim = false;
128   }
129   
130   void useRoundTripSectionMemoryManager() {
131     Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
132       new SectionMemoryManager(),
133       roundTripAllocateCodeSection,
134       roundTripAllocateDataSection,
135       roundTripFinalizeMemory,
136       roundTripDestroy);
137   }
138   
139   void buildMCJITEngine() {
140     ASSERT_EQ(
141       0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
142                                           sizeof(Options), &Error));
143   }
144   
145   void buildAndRunPasses() {
146     LLVMPassManagerRef pass = LLVMCreatePassManager();
147     LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), pass);
148     LLVMAddConstantPropagationPass(pass);
149     LLVMAddInstructionCombiningPass(pass);
150     LLVMRunPassManager(pass, Module);
151     LLVMDisposePassManager(pass);
152   }
153   
154   LLVMModuleRef Module;
155   LLVMValueRef Function;
156   LLVMMCJITCompilerOptions Options;
157   LLVMExecutionEngineRef Engine;
158   char *Error;
159 };
160 } // end anonymous namespace
161
162 TEST_F(MCJITCAPITest, simple_function) {
163   SKIP_UNSUPPORTED_PLATFORM;
164   
165   buildSimpleFunction();
166   buildMCJITOptions();
167   buildMCJITEngine();
168   buildAndRunPasses();
169   
170   union {
171     void *raw;
172     int (*usable)();
173   } functionPointer;
174   functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
175   
176   EXPECT_EQ(42, functionPointer.usable());
177 }
178
179 TEST_F(MCJITCAPITest, custom_memory_manager) {
180   SKIP_UNSUPPORTED_PLATFORM;
181   
182   buildSimpleFunction();
183   buildMCJITOptions();
184   useRoundTripSectionMemoryManager();
185   buildMCJITEngine();
186   buildAndRunPasses();
187   
188   union {
189     void *raw;
190     int (*usable)();
191   } functionPointer;
192   functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
193   
194   EXPECT_EQ(42, functionPointer.usable());
195   EXPECT_TRUE(didCallAllocateCodeSection);
196 }