[weak vtables] Remove a bunch of weak vtables
[oota-llvm.git] / unittests / ExecutionEngine / MCJIT / MCJITTest.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 such as making function
11 // calls, using global variables, and compiling multpile modules.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/ExecutionEngine/MCJIT.h"
16 #include "MCJITTestBase.h"
17 #include "gtest/gtest.h"
18
19 using namespace llvm;
20
21 class MCJITTest : public testing::Test, public MCJITTestBase {
22 protected:
23
24   virtual void SetUp();
25 };
26
27 // Provide out-of-line definition to prevent weak vtable.
28 void MCJITTest::SetUp() {
29   M.reset(createEmptyModule("<main>"));
30 }
31
32 namespace {
33
34 // FIXME: Ensure creating an execution engine does not crash when constructed
35 //        with a null module.
36 /*
37 TEST_F(MCJITTest, null_module) {
38   createJIT(0);
39 }
40 */
41
42 // FIXME: In order to JIT an empty module, there needs to be
43 // an interface to ExecutionEngine that forces compilation but
44 // does not require retrieval of a pointer to a function/global.
45 /*
46 TEST_F(MCJITTest, empty_module) {
47   createJIT(M.take());
48   //EXPECT_NE(0, TheJIT->getObjectImage())
49   //  << "Unable to generate executable loaded object image";
50 }
51 */
52
53 TEST_F(MCJITTest, global_variable) {
54   SKIP_UNSUPPORTED_PLATFORM;
55
56   int initialValue = 5;
57   GlobalValue *Global = insertGlobalInt32(M.get(), "test_global", initialValue);
58   createJIT(M.take());
59   void *globalPtr =  TheJIT->getPointerToGlobal(Global);
60   EXPECT_TRUE(0 != globalPtr)
61     << "Unable to get pointer to global value from JIT";
62
63   EXPECT_EQ(initialValue, *(int32_t*)globalPtr)
64     << "Unexpected initial value of global";
65 }
66
67 TEST_F(MCJITTest, add_function) {
68   SKIP_UNSUPPORTED_PLATFORM;
69
70   Function *F = insertAddFunction(M.get());
71   createJIT(M.take());
72   uint64_t addPtr = TheJIT->getFunctionAddress(F->getName().str());
73   EXPECT_TRUE(0 != addPtr)
74     << "Unable to get pointer to function from JIT";
75
76   ASSERT_TRUE(addPtr != 0) << "Unable to get pointer to function .";
77   int (*AddPtr)(int, int) = (int(*)(int, int))addPtr ;
78   EXPECT_EQ(0,   AddPtr(0, 0));
79   EXPECT_EQ(1,   AddPtr(1, 0));
80   EXPECT_EQ(3,   AddPtr(1, 2));
81   EXPECT_EQ(-5,  AddPtr(-2, -3));
82   EXPECT_EQ(30,  AddPtr(10, 20));
83   EXPECT_EQ(-30, AddPtr(-10, -20));
84   EXPECT_EQ(-40, AddPtr(-10, -30));
85 }
86
87 TEST_F(MCJITTest, run_main) {
88   SKIP_UNSUPPORTED_PLATFORM;
89
90   int rc = 6;
91   Function *Main = insertMainFunction(M.get(), 6);
92   createJIT(M.take());
93   uint64_t ptr = TheJIT->getFunctionAddress(Main->getName().str());
94   EXPECT_TRUE(0 != ptr)
95     << "Unable to get pointer to main() from JIT";
96
97   int (*FuncPtr)(void) = (int(*)(void))ptr;
98   int returnCode = FuncPtr();
99   EXPECT_EQ(returnCode, rc);
100 }
101
102 TEST_F(MCJITTest, return_global) {
103   SKIP_UNSUPPORTED_PLATFORM;
104
105   int32_t initialNum = 7;
106   GlobalVariable *GV = insertGlobalInt32(M.get(), "myglob", initialNum);
107
108   Function *ReturnGlobal = startFunction<int32_t(void)>(M.get(),
109                                                         "ReturnGlobal");
110   Value *ReadGlobal = Builder.CreateLoad(GV);
111   endFunctionWithRet(ReturnGlobal, ReadGlobal);
112
113   createJIT(M.take());
114   uint64_t rgvPtr = TheJIT->getFunctionAddress(ReturnGlobal->getName().str());
115   EXPECT_TRUE(0 != rgvPtr);
116
117   int32_t(*FuncPtr)(void) = (int32_t(*)(void))rgvPtr;
118   EXPECT_EQ(initialNum, FuncPtr())
119     << "Invalid value for global returned from JITted function";
120 }
121
122 // FIXME: This case fails due to a bug with getPointerToGlobal().
123 // The bug is due to MCJIT not having an implementation of getPointerToGlobal()
124 // which results in falling back on the ExecutionEngine implementation that
125 // allocates a new memory block for the global instead of using the same
126 // global variable that is emitted by MCJIT. Hence, the pointer (gvPtr below)
127 // has the correct initial value, but updates to the real global (accessed by
128 // JITted code) are not propagated. Instead, getPointerToGlobal() should return
129 // a pointer into the loaded ObjectImage to reference the emitted global.
130 /*
131 TEST_F(MCJITTest, increment_global) {
132   SKIP_UNSUPPORTED_PLATFORM;
133
134   int32_t initialNum = 5;
135   Function *IncrementGlobal = startFunction<int32_t(void)>(M.get(), "IncrementGlobal");
136   GlobalVariable *GV = insertGlobalInt32(M.get(), "my_global", initialNum);
137   Value *DerefGV = Builder.CreateLoad(GV);
138   Value *AddResult = Builder.CreateAdd(DerefGV,
139                                        ConstantInt::get(Context, APInt(32, 1)));
140   Builder.CreateStore(AddResult, GV);
141   endFunctionWithRet(IncrementGlobal, AddResult);
142
143   createJIT(M.take());
144   void *gvPtr = TheJIT->getPointerToGlobal(GV);
145   EXPECT_EQ(initialNum, *(int32_t*)gvPtr);
146
147   void *vPtr = TheJIT->getFunctionAddress(IncrementGlobal->getName().str());
148   EXPECT_TRUE(0 != vPtr)
149     << "Unable to get pointer to main() from JIT";
150
151   int32_t(*FuncPtr)(void) = (int32_t(*)(void))(intptr_t)vPtr;
152
153   for(int i = 1; i < 3; ++i) {
154     int32_t result = FuncPtr();
155     EXPECT_EQ(initialNum + i, result);            // OK
156     EXPECT_EQ(initialNum + i, *(int32_t*)gvPtr);  // FAILS
157   }
158 }
159 */
160
161 // PR16013: XFAIL this test on ARM, which currently can't handle multiple relocations.
162 #if !defined(__arm__)
163
164 TEST_F(MCJITTest, multiple_functions) {
165   SKIP_UNSUPPORTED_PLATFORM;
166
167   unsigned int numLevels = 23;
168   int32_t innerRetVal= 5;
169
170   Function *Inner = startFunction<int32_t(void)>(M.get(), "Inner");
171   endFunctionWithRet(Inner, ConstantInt::get(Context, APInt(32, innerRetVal)));
172
173   Function *Outer;
174   for (unsigned int i = 0; i < numLevels; ++i) {
175     std::stringstream funcName;
176     funcName << "level_" << i;
177     Outer = startFunction<int32_t(void)>(M.get(), funcName.str());
178     Value *innerResult = Builder.CreateCall(Inner);
179     endFunctionWithRet(Outer, innerResult);
180
181     Inner = Outer;
182   }
183
184   createJIT(M.take());
185   uint64_t ptr = TheJIT->getFunctionAddress(Outer->getName().str());
186   EXPECT_TRUE(0 != ptr)
187     << "Unable to get pointer to outer function from JIT";
188
189   int32_t(*FuncPtr)(void) = (int32_t(*)(void))ptr;
190   EXPECT_EQ(innerRetVal, FuncPtr())
191     << "Incorrect result returned from function";
192 }
193
194 #endif /*!defined(__arm__)*/
195
196 }