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