summaryrefslogtreecommitdiff
path: root/unittests
diff options
context:
space:
mode:
authorLang Hames <lhames@gmail.com>2014-02-12 21:30:07 +0000
committerLang Hames <lhames@gmail.com>2014-02-12 21:30:07 +0000
commit061a739395facc05c5e7dfb7b991dd6cd69ba503 (patch)
tree725ac0d40f51f672a50c6ec0314d6442ddb1537a /unittests
parent29a60e6deba1f4f77d7f688017af66c90f5d6580 (diff)
downloadllvm-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')
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp133
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);
+}