diff options
author | Lang Hames <lhames@gmail.com> | 2014-02-12 21:30:07 +0000 |
---|---|---|
committer | Lang Hames <lhames@gmail.com> | 2014-02-12 21:30:07 +0000 |
commit | 061a739395facc05c5e7dfb7b991dd6cd69ba503 (patch) | |
tree | 725ac0d40f51f672a50c6ec0314d6442ddb1537a /unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp | |
parent | 29a60e6deba1f4f77d7f688017af66c90f5d6580 (diff) | |
download | llvm-061a739395facc05c5e7dfb7b991dd6cd69ba503.tar.gz llvm-061a739395facc05c5e7dfb7b991dd6cd69ba503.tar.bz2 llvm-061a739395facc05c5e7dfb7b991dd6cd69ba503.tar.xz |
Extend RTDyld API to enable optionally precomputing the total amount of memory
required for all sections in a module. This can be useful when targets or
code-models place strict requirements on how sections must be laid out
in memory.
If RTDyldMemoryManger::needsToReserveAllocationSpace() is overridden to return
true then the JIT will call the following method on the memory manager, which
can be used to preallocate the necessary memory.
void RTDyldMemoryManager::reserveAllocationSpace(uintptr_t CodeSize,
uintptr_t DataSizeRO,
uintptr_t DataSizeRW)
Patch by Vaidas Gasiunas. Thanks very much Viadas!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201259 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp')
-rw-r--r-- | unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp | 133 |
1 files changed, 132 insertions, 1 deletions
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp index 4cfb901017..d5b17bff19 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp @@ -21,6 +21,7 @@ #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/Support/Host.h" #include "gtest/gtest.h" +#include "llvm/Support/Debug.h" using namespace llvm; @@ -60,6 +61,54 @@ static void roundTripDestroy(void *object) { } namespace { + +// memory manager to test reserve allocation space callback +class TestReserveAllocationSpaceMemoryManager: public SectionMemoryManager { +public: + uintptr_t ReservedCodeSize; + uintptr_t UsedCodeSize; + uintptr_t ReservedDataSizeRO; + uintptr_t UsedDataSizeRO; + uintptr_t ReservedDataSizeRW; + uintptr_t UsedDataSizeRW; + + TestReserveAllocationSpaceMemoryManager() : + ReservedCodeSize(0), UsedCodeSize(0), ReservedDataSizeRO(0), + UsedDataSizeRO(0), ReservedDataSizeRW(0), UsedDataSizeRW(0) { + } + + virtual bool needsToReserveAllocationSpace() { + return true; + } + + virtual void reserveAllocationSpace( + uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) { + ReservedCodeSize = CodeSize; + ReservedDataSizeRO = DataSizeRO; + ReservedDataSizeRW = DataSizeRW; + } + + void useSpace(uintptr_t* UsedSize, uintptr_t Size, unsigned Alignment) { + uintptr_t AlignedSize = (Size + Alignment - 1) / Alignment * Alignment; + uintptr_t AlignedBegin = (*UsedSize + Alignment - 1) / Alignment * Alignment; + *UsedSize = AlignedBegin + AlignedSize; + } + + virtual uint8_t* allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName, bool IsReadOnly) { + useSpace(IsReadOnly ? &UsedDataSizeRO : &UsedDataSizeRW, Size, Alignment); + return SectionMemoryManager::allocateDataSection(Size, Alignment, + SectionID, SectionName, IsReadOnly); + } + + uint8_t* allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName) { + useSpace(&UsedCodeSize, Size, Alignment); + return SectionMemoryManager::allocateCodeSection(Size, Alignment, + SectionID, SectionName); + } +}; + class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon { protected: MCJITCAPITest() { @@ -119,6 +168,54 @@ protected: LLVMDisposeBuilder(builder); } + void buildModuleWithCodeAndData() { + Module = LLVMModuleCreateWithName("simple_module"); + + LLVMSetTarget(Module, HostTriple.c_str()); + + // build a global variable initialized to "Hello World!" + LLVMValueRef GlobalVar = LLVMAddGlobal(Module, LLVMInt32Type(), "intVal"); + LLVMSetInitializer(GlobalVar, LLVMConstInt(LLVMInt32Type(), 42, 0)); + + { + Function = LLVMAddFunction( + Module, "getGlobal", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0)); + LLVMSetFunctionCallConv(Function, LLVMCCallConv); + + LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function, "entry"); + LLVMBuilderRef Builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(Builder, Entry); + + LLVMValueRef IntVal = LLVMBuildLoad(Builder, GlobalVar, "intVal"); + LLVMBuildRet(Builder, IntVal); + + LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error); + LLVMDisposeMessage(Error); + + LLVMDisposeBuilder(Builder); + } + + { + LLVMTypeRef ParamTypes[] = { LLVMInt32Type() }; + Function2 = LLVMAddFunction( + Module, "setGlobal", LLVMFunctionType(LLVMVoidType(), ParamTypes, 1, 0)); + LLVMSetFunctionCallConv(Function2, LLVMCCallConv); + + LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function2, "entry"); + LLVMBuilderRef Builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(Builder, Entry); + + LLVMValueRef Arg = LLVMGetParam(Function2, 0); + LLVMBuildStore(Builder, Arg, GlobalVar); + LLVMBuildRetVoid(Builder); + + LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error); + LLVMDisposeMessage(Error); + + LLVMDisposeBuilder(Builder); + } + } + void buildMCJITOptions() { LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options)); Options.OptLevel = 2; @@ -135,7 +232,7 @@ protected: roundTripFinalizeMemory, roundTripDestroy); } - + void buildMCJITEngine() { ASSERT_EQ( 0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options, @@ -153,6 +250,7 @@ protected: LLVMModuleRef Module; LLVMValueRef Function; + LLVMValueRef Function2; LLVMMCJITCompilerOptions Options; LLVMExecutionEngineRef Engine; char *Error; @@ -194,3 +292,36 @@ TEST_F(MCJITCAPITest, custom_memory_manager) { EXPECT_EQ(42, functionPointer.usable()); EXPECT_TRUE(didCallAllocateCodeSection); } + +TEST_F(MCJITCAPITest, reserve_allocation_space) { + SKIP_UNSUPPORTED_PLATFORM; + + TestReserveAllocationSpaceMemoryManager* MM = new TestReserveAllocationSpaceMemoryManager(); + + buildModuleWithCodeAndData(); + buildMCJITOptions(); + Options.MCJMM = wrap(MM); + buildMCJITEngine(); + buildAndRunPasses(); + + union { + void *raw; + int (*usable)(); + } GetGlobalFct; + GetGlobalFct.raw = LLVMGetPointerToGlobal(Engine, Function); + + union { + void *raw; + void (*usable)(int); + } SetGlobalFct; + SetGlobalFct.raw = LLVMGetPointerToGlobal(Engine, Function2); + + SetGlobalFct.usable(789); + EXPECT_EQ(789, GetGlobalFct.usable()); + EXPECT_LE(MM->UsedCodeSize, MM->ReservedCodeSize); + EXPECT_LE(MM->UsedDataSizeRO, MM->ReservedDataSizeRO); + EXPECT_LE(MM->UsedDataSizeRW, MM->ReservedDataSizeRW); + EXPECT_TRUE(MM->UsedCodeSize > 0); + EXPECT_TRUE(MM->UsedDataSizeRO > 0); + EXPECT_TRUE(MM->UsedDataSizeRW > 0); +} |