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