cdc52a39b5f24677f202cd093d600b8e080cd973
[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 didCallYield;
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 yield(LLVMContextRef, void *) {
69   didCallYield = true;
70 }
71
72 namespace {
73
74 // memory manager to test reserve allocation space callback
75 class TestReserveAllocationSpaceMemoryManager: public SectionMemoryManager {
76 public:
77   uintptr_t ReservedCodeSize;
78   uintptr_t UsedCodeSize;
79   uintptr_t ReservedDataSizeRO;
80   uintptr_t UsedDataSizeRO;
81   uintptr_t ReservedDataSizeRW;
82   uintptr_t UsedDataSizeRW;
83   
84   TestReserveAllocationSpaceMemoryManager() : 
85     ReservedCodeSize(0), UsedCodeSize(0), ReservedDataSizeRO(0), 
86     UsedDataSizeRO(0), ReservedDataSizeRW(0), UsedDataSizeRW(0) {    
87   }
88
89   bool needsToReserveAllocationSpace() override { return true; }
90
91   void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO,
92                               uintptr_t DataSizeRW) override {
93     ReservedCodeSize = CodeSize;
94     ReservedDataSizeRO = DataSizeRO;
95     ReservedDataSizeRW = DataSizeRW;
96   }
97
98   void useSpace(uintptr_t* UsedSize, uintptr_t Size, unsigned Alignment) {
99     uintptr_t AlignedSize = (Size + Alignment - 1) / Alignment * Alignment;
100     uintptr_t AlignedBegin = (*UsedSize + Alignment - 1) / Alignment * Alignment;
101     *UsedSize = AlignedBegin + AlignedSize;
102   }
103
104   uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
105                                unsigned SectionID, StringRef SectionName,
106                                bool IsReadOnly) override {
107     useSpace(IsReadOnly ? &UsedDataSizeRO : &UsedDataSizeRW, Size, Alignment);
108     return SectionMemoryManager::allocateDataSection(Size, Alignment, 
109       SectionID, SectionName, IsReadOnly);
110   }
111
112   uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
113                                unsigned SectionID,
114                                StringRef SectionName) override {
115     useSpace(&UsedCodeSize, Size, Alignment);
116     return SectionMemoryManager::allocateCodeSection(Size, Alignment, 
117       SectionID, SectionName);
118   }
119 };
120
121 class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
122 protected:
123   MCJITCAPITest() {
124     // The architectures below are known to be compatible with MCJIT as they
125     // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
126     // kept in sync.
127     SupportedArchs.push_back(Triple::aarch64);
128     SupportedArchs.push_back(Triple::arm);
129     SupportedArchs.push_back(Triple::mips);
130     SupportedArchs.push_back(Triple::mips64);
131     SupportedArchs.push_back(Triple::mips64el);
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     UnsupportedEnvironments.push_back(Triple::Cygnus);
145   }
146
147   void SetUp() override {
148     didCallAllocateCodeSection = false;
149     didAllocateCompactUnwindSection = false;
150     didCallYield = false;
151     Module = nullptr;
152     Function = nullptr;
153     Engine = nullptr;
154     Error = nullptr;
155   }
156
157   void TearDown() override {
158     if (Engine)
159       LLVMDisposeExecutionEngine(Engine);
160     else if (Module)
161       LLVMDisposeModule(Module);
162   }
163   
164   void buildSimpleFunction() {
165     Module = LLVMModuleCreateWithName("simple_module");
166     
167     LLVMSetTarget(Module, HostTriple.c_str());
168     
169     Function = LLVMAddFunction(Module, "simple_function",
170                                LLVMFunctionType(LLVMInt32Type(), nullptr,0, 0));
171     LLVMSetFunctionCallConv(Function, LLVMCCallConv);
172     
173     LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
174     LLVMBuilderRef builder = LLVMCreateBuilder();
175     LLVMPositionBuilderAtEnd(builder, entry);
176     LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
177     
178     LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
179     LLVMDisposeMessage(Error);
180     
181     LLVMDisposeBuilder(builder);
182   }
183   
184   void buildFunctionThatUsesStackmap() {
185     Module = LLVMModuleCreateWithName("simple_module");
186     
187     LLVMSetTarget(Module, HostTriple.c_str());
188     
189     LLVMTypeRef stackmapParamTypes[] = { LLVMInt64Type(), LLVMInt32Type() };
190     LLVMValueRef stackmap = LLVMAddFunction(
191       Module, "llvm.experimental.stackmap",
192       LLVMFunctionType(LLVMVoidType(), stackmapParamTypes, 2, 1));
193     LLVMSetLinkage(stackmap, LLVMExternalLinkage);
194     
195     Function = LLVMAddFunction(Module, "simple_function",
196                               LLVMFunctionType(LLVMInt32Type(), nullptr, 0, 0));
197     
198     LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
199     LLVMBuilderRef builder = LLVMCreateBuilder();
200     LLVMPositionBuilderAtEnd(builder, entry);
201     LLVMValueRef stackmapArgs[] = {
202       LLVMConstInt(LLVMInt64Type(), 0, 0), LLVMConstInt(LLVMInt32Type(), 5, 0),
203       LLVMConstInt(LLVMInt32Type(), 42, 0)
204     };
205     LLVMBuildCall(builder, stackmap, stackmapArgs, 3, "");
206     LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
207     
208     LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
209     LLVMDisposeMessage(Error);
210     
211     LLVMDisposeBuilder(builder);
212   }
213   
214   void buildModuleWithCodeAndData() {
215     Module = LLVMModuleCreateWithName("simple_module");
216     
217     LLVMSetTarget(Module, HostTriple.c_str());
218     
219     // build a global int32 variable initialized to 42.
220     LLVMValueRef GlobalVar = LLVMAddGlobal(Module, LLVMInt32Type(), "intVal");    
221     LLVMSetInitializer(GlobalVar, LLVMConstInt(LLVMInt32Type(), 42, 0));
222     
223     {
224         Function = LLVMAddFunction(Module, "getGlobal",
225                               LLVMFunctionType(LLVMInt32Type(), nullptr, 0, 0));
226         LLVMSetFunctionCallConv(Function, LLVMCCallConv);
227         
228         LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function, "entry");
229         LLVMBuilderRef Builder = LLVMCreateBuilder();
230         LLVMPositionBuilderAtEnd(Builder, Entry);
231         
232         LLVMValueRef IntVal = LLVMBuildLoad(Builder, GlobalVar, "intVal");
233         LLVMBuildRet(Builder, IntVal);
234         
235         LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
236         LLVMDisposeMessage(Error);
237         
238         LLVMDisposeBuilder(Builder);
239     }
240     
241     {
242         LLVMTypeRef ParamTypes[] = { LLVMInt32Type() };
243         Function2 = LLVMAddFunction(
244           Module, "setGlobal", LLVMFunctionType(LLVMVoidType(), ParamTypes, 1, 0));
245         LLVMSetFunctionCallConv(Function2, LLVMCCallConv);
246         
247         LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function2, "entry");
248         LLVMBuilderRef Builder = LLVMCreateBuilder();
249         LLVMPositionBuilderAtEnd(Builder, Entry);
250         
251         LLVMValueRef Arg = LLVMGetParam(Function2, 0);
252         LLVMBuildStore(Builder, Arg, GlobalVar);
253         LLVMBuildRetVoid(Builder);
254         
255         LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
256         LLVMDisposeMessage(Error);
257         
258         LLVMDisposeBuilder(Builder);
259     }
260   }
261   
262   void buildMCJITOptions() {
263     LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
264     Options.OptLevel = 2;
265     
266     // Just ensure that this field still exists.
267     Options.NoFramePointerElim = false;
268   }
269   
270   void useRoundTripSectionMemoryManager() {
271     Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
272       new SectionMemoryManager(),
273       roundTripAllocateCodeSection,
274       roundTripAllocateDataSection,
275       roundTripFinalizeMemory,
276       roundTripDestroy);
277   }
278
279   void buildMCJITEngine() {
280     ASSERT_EQ(
281       0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
282                                           sizeof(Options), &Error));
283   }
284   
285   void buildAndRunPasses() {
286     LLVMPassManagerRef pass = LLVMCreatePassManager();
287     LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), pass);
288     LLVMAddConstantPropagationPass(pass);
289     LLVMAddInstructionCombiningPass(pass);
290     LLVMRunPassManager(pass, Module);
291     LLVMDisposePassManager(pass);
292   }
293   
294   void buildAndRunOptPasses() {
295     LLVMPassManagerBuilderRef passBuilder;
296     
297     passBuilder = LLVMPassManagerBuilderCreate();
298     LLVMPassManagerBuilderSetOptLevel(passBuilder, 2);
299     LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0);
300     
301     LLVMPassManagerRef functionPasses =
302       LLVMCreateFunctionPassManagerForModule(Module);
303     LLVMPassManagerRef modulePasses =
304       LLVMCreatePassManager();
305     
306     LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), modulePasses);
307     
308     LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder,
309                                                       functionPasses);
310     LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses);
311     
312     LLVMPassManagerBuilderDispose(passBuilder);
313     
314     LLVMInitializeFunctionPassManager(functionPasses);
315     for (LLVMValueRef value = LLVMGetFirstFunction(Module);
316          value; value = LLVMGetNextFunction(value))
317       LLVMRunFunctionPassManager(functionPasses, value);
318     LLVMFinalizeFunctionPassManager(functionPasses);
319     
320     LLVMRunPassManager(modulePasses, Module);
321     
322     LLVMDisposePassManager(functionPasses);
323     LLVMDisposePassManager(modulePasses);
324   }
325   
326   LLVMModuleRef Module;
327   LLVMValueRef Function;
328   LLVMValueRef Function2;
329   LLVMMCJITCompilerOptions Options;
330   LLVMExecutionEngineRef Engine;
331   char *Error;
332 };
333 } // end anonymous namespace
334
335 TEST_F(MCJITCAPITest, simple_function) {
336   SKIP_UNSUPPORTED_PLATFORM;
337   
338   buildSimpleFunction();
339   buildMCJITOptions();
340   buildMCJITEngine();
341   buildAndRunPasses();
342   
343   union {
344     void *raw;
345     int (*usable)();
346   } functionPointer;
347   functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
348   
349   EXPECT_EQ(42, functionPointer.usable());
350 }
351
352 TEST_F(MCJITCAPITest, gva) {
353   SKIP_UNSUPPORTED_PLATFORM;
354
355   Module = LLVMModuleCreateWithName("simple_module");
356   LLVMSetTarget(Module, HostTriple.c_str());
357   LLVMValueRef GlobalVar = LLVMAddGlobal(Module, LLVMInt32Type(), "simple_value");
358   LLVMSetInitializer(GlobalVar, LLVMConstInt(LLVMInt32Type(), 42, 0));
359
360   buildMCJITOptions();
361   buildMCJITEngine();
362   buildAndRunPasses();
363
364   uint64_t raw = LLVMGetGlobalValueAddress(Engine, "simple_value");
365   int32_t *usable  = (int32_t *) raw;
366
367   EXPECT_EQ(42, *usable);
368 }
369
370 TEST_F(MCJITCAPITest, gfa) {
371   SKIP_UNSUPPORTED_PLATFORM;
372
373   buildSimpleFunction();
374   buildMCJITOptions();
375   buildMCJITEngine();
376   buildAndRunPasses();
377
378   uint64_t raw = LLVMGetFunctionAddress(Engine, "simple_function");
379   int (*usable)() = (int (*)()) raw;
380
381   EXPECT_EQ(42, usable());
382 }
383
384 TEST_F(MCJITCAPITest, custom_memory_manager) {
385   SKIP_UNSUPPORTED_PLATFORM;
386   
387   buildSimpleFunction();
388   buildMCJITOptions();
389   useRoundTripSectionMemoryManager();
390   buildMCJITEngine();
391   buildAndRunPasses();
392   
393   union {
394     void *raw;
395     int (*usable)();
396   } functionPointer;
397   functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
398   
399   EXPECT_EQ(42, functionPointer.usable());
400   EXPECT_TRUE(didCallAllocateCodeSection);
401 }
402
403 TEST_F(MCJITCAPITest, stackmap_creates_compact_unwind_on_darwin) {
404   SKIP_UNSUPPORTED_PLATFORM;
405   
406   // This test is also not supported on non-x86 platforms.
407   if (Triple(HostTriple).getArch() != Triple::x86_64)
408     return;
409   
410   buildFunctionThatUsesStackmap();
411   buildMCJITOptions();
412   useRoundTripSectionMemoryManager();
413   buildMCJITEngine();
414   buildAndRunOptPasses();
415   
416   union {
417     void *raw;
418     int (*usable)();
419   } functionPointer;
420   functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
421   
422   EXPECT_EQ(42, functionPointer.usable());
423   EXPECT_TRUE(didCallAllocateCodeSection);
424   
425   // Up to this point, the test is specific only to X86-64. But this next
426   // expectation is only valid on Darwin because it assumes that unwind
427   // data is made available only through compact_unwind. It would be
428   // worthwhile to extend this to handle non-Darwin platforms, in which
429   // case you'd want to look for an eh_frame or something.
430   //
431   // FIXME: Currently, MCJIT relies on a configure-time check to determine which
432   // sections to emit. The JIT client should have runtime control over this.
433   EXPECT_TRUE(
434     Triple(HostTriple).getOS() != Triple::Darwin ||
435     Triple(HostTriple).isMacOSXVersionLT(10, 7) ||
436     didAllocateCompactUnwindSection);
437 }
438
439 TEST_F(MCJITCAPITest, reserve_allocation_space) {
440   SKIP_UNSUPPORTED_PLATFORM;
441   
442   TestReserveAllocationSpaceMemoryManager* MM = new TestReserveAllocationSpaceMemoryManager();
443   
444   buildModuleWithCodeAndData();
445   buildMCJITOptions();
446   Options.MCJMM = wrap(MM);
447   buildMCJITEngine();
448   buildAndRunPasses();
449   
450   union {
451     void *raw;
452     int (*usable)();
453   } GetGlobalFct;
454   GetGlobalFct.raw = LLVMGetPointerToGlobal(Engine, Function);
455   
456   union {
457     void *raw;
458     void (*usable)(int);
459   } SetGlobalFct;
460   SetGlobalFct.raw = LLVMGetPointerToGlobal(Engine, Function2);
461   
462   SetGlobalFct.usable(789);
463   EXPECT_EQ(789, GetGlobalFct.usable());
464   EXPECT_LE(MM->UsedCodeSize, MM->ReservedCodeSize);
465   EXPECT_LE(MM->UsedDataSizeRO, MM->ReservedDataSizeRO);
466   EXPECT_LE(MM->UsedDataSizeRW, MM->ReservedDataSizeRW);
467   EXPECT_TRUE(MM->UsedCodeSize > 0); 
468   EXPECT_TRUE(MM->UsedDataSizeRW > 0);
469 }
470
471 TEST_F(MCJITCAPITest, yield) {
472   SKIP_UNSUPPORTED_PLATFORM;
473
474   buildSimpleFunction();
475   buildMCJITOptions();
476   buildMCJITEngine();
477   LLVMContextRef C = LLVMGetGlobalContext();
478   LLVMContextSetYieldCallback(C, yield, nullptr);
479   buildAndRunPasses();
480
481   union {
482     void *raw;
483     int (*usable)();
484   } functionPointer;
485   functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
486
487   EXPECT_EQ(42, functionPointer.usable());
488   EXPECT_TRUE(didCallYield);
489 }
490
491 static int localTestFunc() {
492   return 42;
493 }
494
495 TEST_F(MCJITCAPITest, addGlobalMapping) {
496   SKIP_UNSUPPORTED_PLATFORM;
497
498   Module = LLVMModuleCreateWithName("testModule");
499   LLVMSetTarget(Module, HostTriple.c_str());
500   LLVMTypeRef FunctionType = LLVMFunctionType(LLVMInt32Type(), NULL, 0, 0);
501   LLVMValueRef MappedFn = LLVMAddFunction(Module, "mapped_fn", FunctionType);
502
503   Function = LLVMAddFunction(Module, "test_fn", FunctionType);
504   LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function, "");
505   LLVMBuilderRef Builder = LLVMCreateBuilder();
506   LLVMPositionBuilderAtEnd(Builder, Entry);
507   LLVMValueRef RetVal = LLVMBuildCall(Builder, MappedFn, NULL, 0, "");
508   LLVMBuildRet(Builder, RetVal);
509   LLVMDisposeBuilder(Builder);
510
511   LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
512   LLVMDisposeMessage(Error);
513
514   buildMCJITOptions();
515   buildMCJITEngine();
516
517   union {
518     int (*raw)();
519     void *usable;
520   } functionPointer;
521   functionPointer.raw = &localTestFunc;
522
523   LLVMAddGlobalMapping(Engine, MappedFn, functionPointer.usable);
524
525   buildAndRunPasses();
526
527   uint64_t raw = LLVMGetFunctionAddress(Engine, "test_fn");
528   int (*usable)() = (int (*)()) raw;
529
530   EXPECT_EQ(42, usable());
531 }