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