This test was failing on non-X86-64 platforms because stackmaps only work on X86-64.
[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 "MCJITTestAPICommon.h"
17 #include "llvm-c/Core.h"
18 #include "llvm-c/ExecutionEngine.h"
19 #include "llvm-c/Target.h"
20 #include "llvm-c/Transforms/Scalar.h"
21 #include "llvm-c/Transforms/PassManagerBuilder.h"
22 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
23 #include "llvm/Support/Host.h"
24 #include "gtest/gtest.h"
25 #include "llvm/Support/Debug.h"
26
27 using namespace llvm;
28
29 static bool didCallAllocateCodeSection;
30 static bool didAllocateCompactUnwindSection;
31
32 static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
33                                              unsigned alignment,
34                                              unsigned sectionID,
35                                              const char *sectionName) {
36   didCallAllocateCodeSection = true;
37   return static_cast<SectionMemoryManager*>(object)->allocateCodeSection(
38     size, alignment, sectionID, sectionName);
39 }
40
41 static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size,
42                                              unsigned alignment,
43                                              unsigned sectionID,
44                                              const char *sectionName,
45                                              LLVMBool isReadOnly) {
46   if (!strcmp(sectionName, "__compact_unwind"))
47     didAllocateCompactUnwindSection = true;
48   return static_cast<SectionMemoryManager*>(object)->allocateDataSection(
49     size, alignment, sectionID, sectionName, isReadOnly);
50 }
51
52 static LLVMBool roundTripFinalizeMemory(void *object, char **errMsg) {
53   std::string errMsgString;
54   bool result =
55     static_cast<SectionMemoryManager*>(object)->finalizeMemory(&errMsgString);
56   if (result) {
57     *errMsg = LLVMCreateMessage(errMsgString.c_str());
58     return 1;
59   }
60   return 0;
61 }
62
63 static void roundTripDestroy(void *object) {
64   delete static_cast<SectionMemoryManager*>(object);
65 }
66
67 namespace {
68
69 // memory manager to test reserve allocation space callback
70 class TestReserveAllocationSpaceMemoryManager: public SectionMemoryManager {
71 public:
72   uintptr_t ReservedCodeSize;
73   uintptr_t UsedCodeSize;
74   uintptr_t ReservedDataSizeRO;
75   uintptr_t UsedDataSizeRO;
76   uintptr_t ReservedDataSizeRW;
77   uintptr_t UsedDataSizeRW;
78   
79   TestReserveAllocationSpaceMemoryManager() : 
80     ReservedCodeSize(0), UsedCodeSize(0), ReservedDataSizeRO(0), 
81     UsedDataSizeRO(0), ReservedDataSizeRW(0), UsedDataSizeRW(0) {    
82   }
83   
84   virtual bool needsToReserveAllocationSpace() {
85     return true;
86   }
87
88   virtual void reserveAllocationSpace(
89       uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) {
90     ReservedCodeSize = CodeSize;
91     ReservedDataSizeRO = DataSizeRO;
92     ReservedDataSizeRW = DataSizeRW;
93   }
94
95   void useSpace(uintptr_t* UsedSize, uintptr_t Size, unsigned Alignment) {
96     uintptr_t AlignedSize = (Size + Alignment - 1) / Alignment * Alignment;
97     uintptr_t AlignedBegin = (*UsedSize + Alignment - 1) / Alignment * Alignment;
98     *UsedSize = AlignedBegin + AlignedSize;
99   }
100
101   virtual uint8_t* allocateDataSection(uintptr_t Size, unsigned Alignment,
102       unsigned SectionID, StringRef SectionName, bool IsReadOnly) {
103     useSpace(IsReadOnly ? &UsedDataSizeRO : &UsedDataSizeRW, Size, Alignment);
104     return SectionMemoryManager::allocateDataSection(Size, Alignment, 
105       SectionID, SectionName, IsReadOnly);
106   }
107
108   uint8_t* allocateCodeSection(uintptr_t Size, unsigned Alignment, 
109       unsigned SectionID, StringRef SectionName) {
110     useSpace(&UsedCodeSize, Size, Alignment);
111     return SectionMemoryManager::allocateCodeSection(Size, Alignment, 
112       SectionID, SectionName);
113   }
114 };
115
116 class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
117 protected:
118   MCJITCAPITest() {
119     // The architectures below are known to be compatible with MCJIT as they
120     // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
121     // kept in sync.
122     SupportedArchs.push_back(Triple::aarch64);
123     SupportedArchs.push_back(Triple::arm);
124     SupportedArchs.push_back(Triple::mips);
125     SupportedArchs.push_back(Triple::x86);
126     SupportedArchs.push_back(Triple::x86_64);
127
128     // Some architectures have sub-architectures in which tests will fail, like
129     // ARM. These two vectors will define if they do have sub-archs (to avoid
130     // extra work for those who don't), and if so, if they are listed to work
131     HasSubArchs.push_back(Triple::arm);
132     SupportedSubArchs.push_back("armv6");
133     SupportedSubArchs.push_back("armv7");
134
135     // The operating systems below are known to be sufficiently incompatible
136     // that they will fail the MCJIT C API tests.
137     UnsupportedOSs.push_back(Triple::Cygwin);
138   }
139   
140   virtual void SetUp() {
141     didCallAllocateCodeSection = false;
142     didAllocateCompactUnwindSection = false;
143     Module = 0;
144     Function = 0;
145     Engine = 0;
146     Error = 0;
147   }
148   
149   virtual void TearDown() {
150     if (Engine)
151       LLVMDisposeExecutionEngine(Engine);
152     else if (Module)
153       LLVMDisposeModule(Module);
154   }
155   
156   void buildSimpleFunction() {
157     Module = LLVMModuleCreateWithName("simple_module");
158     
159     LLVMSetTarget(Module, HostTriple.c_str());
160     
161     Function = LLVMAddFunction(
162       Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
163     LLVMSetFunctionCallConv(Function, LLVMCCallConv);
164     
165     LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
166     LLVMBuilderRef builder = LLVMCreateBuilder();
167     LLVMPositionBuilderAtEnd(builder, entry);
168     LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
169     
170     LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
171     LLVMDisposeMessage(Error);
172     
173     LLVMDisposeBuilder(builder);
174   }
175   
176   void buildFunctionThatUsesStackmap() {
177     Module = LLVMModuleCreateWithName("simple_module");
178     
179     LLVMSetTarget(Module, HostTriple.c_str());
180     
181     LLVMTypeRef stackmapParamTypes[] = { LLVMInt64Type(), LLVMInt32Type() };
182     LLVMValueRef stackmap = LLVMAddFunction(
183       Module, "llvm.experimental.stackmap",
184       LLVMFunctionType(LLVMVoidType(), stackmapParamTypes, 2, 1));
185     LLVMSetLinkage(stackmap, LLVMExternalLinkage);
186     
187     Function = LLVMAddFunction(
188       Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
189     
190     LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
191     LLVMBuilderRef builder = LLVMCreateBuilder();
192     LLVMPositionBuilderAtEnd(builder, entry);
193     LLVMValueRef stackmapArgs[] = {
194       LLVMConstInt(LLVMInt64Type(), 0, 0), LLVMConstInt(LLVMInt32Type(), 5, 0),
195       LLVMConstInt(LLVMInt32Type(), 42, 0)
196     };
197     LLVMBuildCall(builder, stackmap, stackmapArgs, 3, "");
198     LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
199     
200     LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
201     LLVMDisposeMessage(Error);
202     
203     LLVMDisposeBuilder(builder);
204   }
205   
206   void buildModuleWithCodeAndData() {
207     Module = LLVMModuleCreateWithName("simple_module");
208     
209     LLVMSetTarget(Module, HostTriple.c_str());
210     
211     // build a global int32 variable initialized to 42.
212     LLVMValueRef GlobalVar = LLVMAddGlobal(Module, LLVMInt32Type(), "intVal");    
213     LLVMSetInitializer(GlobalVar, LLVMConstInt(LLVMInt32Type(), 42, 0));
214     
215     {
216         Function = LLVMAddFunction(
217           Module, "getGlobal", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
218         LLVMSetFunctionCallConv(Function, LLVMCCallConv);
219         
220         LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function, "entry");
221         LLVMBuilderRef Builder = LLVMCreateBuilder();
222         LLVMPositionBuilderAtEnd(Builder, Entry);
223         
224         LLVMValueRef IntVal = LLVMBuildLoad(Builder, GlobalVar, "intVal");
225         LLVMBuildRet(Builder, IntVal);
226         
227         LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
228         LLVMDisposeMessage(Error);
229         
230         LLVMDisposeBuilder(Builder);
231     }
232     
233     {
234         LLVMTypeRef ParamTypes[] = { LLVMInt32Type() };
235         Function2 = LLVMAddFunction(
236           Module, "setGlobal", LLVMFunctionType(LLVMVoidType(), ParamTypes, 1, 0));
237         LLVMSetFunctionCallConv(Function2, LLVMCCallConv);
238         
239         LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function2, "entry");
240         LLVMBuilderRef Builder = LLVMCreateBuilder();
241         LLVMPositionBuilderAtEnd(Builder, Entry);
242         
243         LLVMValueRef Arg = LLVMGetParam(Function2, 0);
244         LLVMBuildStore(Builder, Arg, GlobalVar);
245         LLVMBuildRetVoid(Builder);
246         
247         LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
248         LLVMDisposeMessage(Error);
249         
250         LLVMDisposeBuilder(Builder);
251     }
252   }
253   
254   void buildMCJITOptions() {
255     LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
256     Options.OptLevel = 2;
257     
258     // Just ensure that this field still exists.
259     Options.NoFramePointerElim = false;
260   }
261   
262   void useRoundTripSectionMemoryManager() {
263     Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
264       new SectionMemoryManager(),
265       roundTripAllocateCodeSection,
266       roundTripAllocateDataSection,
267       roundTripFinalizeMemory,
268       roundTripDestroy);
269   }
270
271   void buildMCJITEngine() {
272     ASSERT_EQ(
273       0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
274                                           sizeof(Options), &Error));
275   }
276   
277   void buildAndRunPasses() {
278     LLVMPassManagerRef pass = LLVMCreatePassManager();
279     LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), pass);
280     LLVMAddConstantPropagationPass(pass);
281     LLVMAddInstructionCombiningPass(pass);
282     LLVMRunPassManager(pass, Module);
283     LLVMDisposePassManager(pass);
284   }
285   
286   void buildAndRunOptPasses() {
287     LLVMPassManagerBuilderRef passBuilder;
288     
289     passBuilder = LLVMPassManagerBuilderCreate();
290     LLVMPassManagerBuilderSetOptLevel(passBuilder, 2);
291     LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0);
292     
293     LLVMPassManagerRef functionPasses =
294       LLVMCreateFunctionPassManagerForModule(Module);
295     LLVMPassManagerRef modulePasses =
296       LLVMCreatePassManager();
297     
298     LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), modulePasses);
299     
300     LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder,
301                                                       functionPasses);
302     LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses);
303     
304     LLVMPassManagerBuilderDispose(passBuilder);
305     
306     LLVMInitializeFunctionPassManager(functionPasses);
307     for (LLVMValueRef value = LLVMGetFirstFunction(Module);
308          value; value = LLVMGetNextFunction(value))
309       LLVMRunFunctionPassManager(functionPasses, value);
310     LLVMFinalizeFunctionPassManager(functionPasses);
311     
312     LLVMRunPassManager(modulePasses, Module);
313     
314     LLVMDisposePassManager(functionPasses);
315     LLVMDisposePassManager(modulePasses);
316   }
317   
318   LLVMModuleRef Module;
319   LLVMValueRef Function;
320   LLVMValueRef Function2;
321   LLVMMCJITCompilerOptions Options;
322   LLVMExecutionEngineRef Engine;
323   char *Error;
324 };
325 } // end anonymous namespace
326
327 TEST_F(MCJITCAPITest, simple_function) {
328   SKIP_UNSUPPORTED_PLATFORM;
329   
330   buildSimpleFunction();
331   buildMCJITOptions();
332   buildMCJITEngine();
333   buildAndRunPasses();
334   
335   union {
336     void *raw;
337     int (*usable)();
338   } functionPointer;
339   functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
340   
341   EXPECT_EQ(42, functionPointer.usable());
342 }
343
344 TEST_F(MCJITCAPITest, custom_memory_manager) {
345   SKIP_UNSUPPORTED_PLATFORM;
346   
347   buildSimpleFunction();
348   buildMCJITOptions();
349   useRoundTripSectionMemoryManager();
350   buildMCJITEngine();
351   buildAndRunPasses();
352   
353   union {
354     void *raw;
355     int (*usable)();
356   } functionPointer;
357   functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
358   
359   EXPECT_EQ(42, functionPointer.usable());
360   EXPECT_TRUE(didCallAllocateCodeSection);
361 }
362
363 TEST_F(MCJITCAPITest, stackmap_creates_compact_unwind_on_darwin) {
364   SKIP_UNSUPPORTED_PLATFORM;
365   
366   // This test is also not supported on non-x86 platforms.
367   if (Triple(HostTriple).getArch() != Triple::x86_64)
368     return;
369   
370   buildFunctionThatUsesStackmap();
371   buildMCJITOptions();
372   useRoundTripSectionMemoryManager();
373   buildMCJITEngine();
374   buildAndRunOptPasses();
375   
376   union {
377     void *raw;
378     int (*usable)();
379   } functionPointer;
380   functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
381   
382   EXPECT_EQ(42, functionPointer.usable());
383   EXPECT_TRUE(didCallAllocateCodeSection);
384   
385   // Up to this point, the test is specific only to X86-64. But this next
386   // expectation is only valid on Darwin because it assumes that unwind
387   // data is made available only through compact_unwind. It would be
388   // worthwhile to extend this to handle non-Darwin platforms, in which
389   // case you'd want to look for an eh_frame or something.
390   EXPECT_TRUE(
391     Triple(HostTriple).getOS() != Triple::Darwin ||
392     didAllocateCompactUnwindSection);
393 }
394
395 TEST_F(MCJITCAPITest, reserve_allocation_space) {
396   SKIP_UNSUPPORTED_PLATFORM;
397   
398   TestReserveAllocationSpaceMemoryManager* MM = new TestReserveAllocationSpaceMemoryManager();
399   
400   buildModuleWithCodeAndData();
401   buildMCJITOptions();
402   Options.MCJMM = wrap(MM);
403   buildMCJITEngine();
404   buildAndRunPasses();
405   
406   union {
407     void *raw;
408     int (*usable)();
409   } GetGlobalFct;
410   GetGlobalFct.raw = LLVMGetPointerToGlobal(Engine, Function);
411   
412   union {
413     void *raw;
414     void (*usable)(int);
415   } SetGlobalFct;
416   SetGlobalFct.raw = LLVMGetPointerToGlobal(Engine, Function2);
417   
418   SetGlobalFct.usable(789);
419   EXPECT_EQ(789, GetGlobalFct.usable());
420   EXPECT_LE(MM->UsedCodeSize, MM->ReservedCodeSize);
421   EXPECT_LE(MM->UsedDataSizeRO, MM->ReservedDataSizeRO);
422   EXPECT_LE(MM->UsedDataSizeRW, MM->ReservedDataSizeRW);
423   EXPECT_TRUE(MM->UsedCodeSize > 0); 
424   EXPECT_TRUE(MM->UsedDataSizeRW > 0);
425 }