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