aboutsummaryrefslogtreecommitdiffstats
path: root/unittests/ExecutionEngine/MCJIT
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/ExecutionEngine/MCJIT')
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp169
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp6
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp5
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITTest.cpp23
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h20
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITTestBase.h13
6 files changed, 178 insertions, 58 deletions
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
index d8cf6c5..c434a7c 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
+++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
@@ -17,79 +17,176 @@
#include "llvm-c/ExecutionEngine.h"
#include "llvm-c/Target.h"
#include "llvm-c/Transforms/Scalar.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/Support/Host.h"
#include "MCJITTestAPICommon.h"
#include "gtest/gtest.h"
using namespace llvm;
+static bool didCallAllocateCodeSection;
+
+static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
+ unsigned alignment,
+ unsigned sectionID) {
+ didCallAllocateCodeSection = true;
+ return static_cast<SectionMemoryManager*>(object)->allocateCodeSection(
+ size, alignment, sectionID);
+}
+
+static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size,
+ unsigned alignment,
+ unsigned sectionID,
+ LLVMBool isReadOnly) {
+ return static_cast<SectionMemoryManager*>(object)->allocateDataSection(
+ size, alignment, sectionID, isReadOnly);
+}
+
+static LLVMBool roundTripFinalizeMemory(void *object, char **errMsg) {
+ std::string errMsgString;
+ bool result =
+ static_cast<SectionMemoryManager*>(object)->finalizeMemory(&errMsgString);
+ if (result) {
+ *errMsg = LLVMCreateMessage(errMsgString.c_str());
+ return 1;
+ }
+ return 0;
+}
+
+static void roundTripDestroy(void *object) {
+ delete static_cast<SectionMemoryManager*>(object);
+}
+
class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
protected:
MCJITCAPITest() {
// The architectures below are known to be compatible with MCJIT as they
// are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
// kept in sync.
+ SupportedArchs.push_back(Triple::aarch64);
SupportedArchs.push_back(Triple::arm);
SupportedArchs.push_back(Triple::mips);
SupportedArchs.push_back(Triple::x86);
SupportedArchs.push_back(Triple::x86_64);
+ // Some architectures have sub-architectures in which tests will fail, like
+ // ARM. These two vectors will define if they do have sub-archs (to avoid
+ // extra work for those who don't), and if so, if they are listed to work
+ HasSubArchs.push_back(Triple::arm);
+ SupportedSubArchs.push_back("armv6");
+ SupportedSubArchs.push_back("armv7");
+
// The operating systems below are known to be sufficiently incompatible
// that they will fail the MCJIT C API tests.
UnsupportedOSs.push_back(Triple::Cygwin);
}
-};
-
-TEST_F(MCJITCAPITest, simple_function) {
- SKIP_UNSUPPORTED_PLATFORM;
- char *error = 0;
+ virtual void SetUp() {
+ didCallAllocateCodeSection = false;
+ Module = 0;
+ Function = 0;
+ Engine = 0;
+ Error = 0;
+ }
- // Creates a function that returns 42, compiles it, and runs it.
+ virtual void TearDown() {
+ if (Engine)
+ LLVMDisposeExecutionEngine(Engine);
+ else if (Module)
+ LLVMDisposeModule(Module);
+ }
- LLVMModuleRef module = LLVMModuleCreateWithName("simple_module");
+ void buildSimpleFunction() {
+ Module = LLVMModuleCreateWithName("simple_module");
+
+ LLVMSetTarget(Module, HostTriple.c_str());
+
+ Function = LLVMAddFunction(
+ Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
+ LLVMSetFunctionCallConv(Function, LLVMCCallConv);
+
+ LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
+ LLVMBuilderRef builder = LLVMCreateBuilder();
+ LLVMPositionBuilderAtEnd(builder, entry);
+ LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
+
+ LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
+ LLVMDisposeMessage(Error);
+
+ LLVMDisposeBuilder(builder);
+ }
- LLVMValueRef function = LLVMAddFunction(
- module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
- LLVMSetFunctionCallConv(function, LLVMCCallConv);
+ void buildMCJITOptions() {
+ LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
+ Options.OptLevel = 2;
+
+ // Just ensure that this field still exists.
+ Options.NoFramePointerElim = false;
+ }
- LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry");
- LLVMBuilderRef builder = LLVMCreateBuilder();
- LLVMPositionBuilderAtEnd(builder, entry);
- LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
+ void useRoundTripSectionMemoryManager() {
+ Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
+ new SectionMemoryManager(),
+ roundTripAllocateCodeSection,
+ roundTripAllocateDataSection,
+ roundTripFinalizeMemory,
+ roundTripDestroy);
+ }
- LLVMVerifyModule(module, LLVMAbortProcessAction, &error);
- LLVMDisposeMessage(error);
+ void buildMCJITEngine() {
+ ASSERT_EQ(
+ 0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
+ sizeof(Options), &Error));
+ }
- LLVMDisposeBuilder(builder);
+ void buildAndRunPasses() {
+ LLVMPassManagerRef pass = LLVMCreatePassManager();
+ LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), pass);
+ LLVMAddConstantPropagationPass(pass);
+ LLVMAddInstructionCombiningPass(pass);
+ LLVMRunPassManager(pass, Module);
+ LLVMDisposePassManager(pass);
+ }
- LLVMMCJITCompilerOptions options;
- LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));
- options.OptLevel = 2;
+ LLVMModuleRef Module;
+ LLVMValueRef Function;
+ LLVMMCJITCompilerOptions Options;
+ LLVMExecutionEngineRef Engine;
+ char *Error;
+};
+
+TEST_F(MCJITCAPITest, simple_function) {
+ SKIP_UNSUPPORTED_PLATFORM;
- // Just ensure that this field still exists.
- options.NoFramePointerElim = false;
+ buildSimpleFunction();
+ buildMCJITOptions();
+ buildMCJITEngine();
+ buildAndRunPasses();
+
+ union {
+ void *raw;
+ int (*usable)();
+ } functionPointer;
+ functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
- LLVMExecutionEngineRef engine;
- ASSERT_EQ(
- 0, LLVMCreateMCJITCompilerForModule(&engine, module, &options,
- sizeof(options), &error));
+ EXPECT_EQ(42, functionPointer.usable());
+}
+
+TEST_F(MCJITCAPITest, custom_memory_manager) {
+ SKIP_UNSUPPORTED_PLATFORM;
- LLVMPassManagerRef pass = LLVMCreatePassManager();
- LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass);
- LLVMAddConstantPropagationPass(pass);
- LLVMAddInstructionCombiningPass(pass);
- LLVMRunPassManager(pass, module);
- LLVMDisposePassManager(pass);
+ buildSimpleFunction();
+ buildMCJITOptions();
+ useRoundTripSectionMemoryManager();
+ buildMCJITEngine();
+ buildAndRunPasses();
union {
void *raw;
int (*usable)();
} functionPointer;
- functionPointer.raw = LLVMGetPointerToGlobal(engine, function);
+ functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
EXPECT_EQ(42, functionPointer.usable());
-
- LLVMDisposeExecutionEngine(engine);
+ EXPECT_TRUE(didCallAllocateCodeSection);
}
-
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp
index ab09aca..9e0b353 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp
+++ b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp
@@ -46,7 +46,7 @@ TEST(MCJITMemoryManagerTest, BasicAllocations) {
}
std::string Error;
- EXPECT_FALSE(MemMgr->applyPermissions(&Error));
+ EXPECT_FALSE(MemMgr->finalizeMemory(&Error));
}
TEST(MCJITMemoryManagerTest, LargeAllocations) {
@@ -79,7 +79,7 @@ TEST(MCJITMemoryManagerTest, LargeAllocations) {
}
std::string Error;
- EXPECT_FALSE(MemMgr->applyPermissions(&Error));
+ EXPECT_FALSE(MemMgr->finalizeMemory(&Error));
}
TEST(MCJITMemoryManagerTest, ManyAllocations) {
@@ -114,7 +114,7 @@ TEST(MCJITMemoryManagerTest, ManyAllocations) {
}
std::string Error;
- EXPECT_FALSE(MemMgr->applyPermissions(&Error));
+ EXPECT_FALSE(MemMgr->finalizeMemory(&Error));
}
TEST(MCJITMemoryManagerTest, ManyVariedAllocations) {
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp
index 0061e30..32fc292 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp
+++ b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp
@@ -98,14 +98,13 @@ protected:
void compileAndRun(int ExpectedRC = OriginalRC) {
// This function shouldn't be called until after SetUp.
- ASSERT_TRUE(0 != TheJIT);
+ ASSERT_TRUE(TheJIT.isValid());
ASSERT_TRUE(0 != Main);
+ // We may be using a null cache, so ensure compilation is valid.
TheJIT->finalizeObject();
void *vPtr = TheJIT->getPointerToFunction(Main);
- static_cast<SectionMemoryManager*>(MM)->invalidateInstructionCache();
-
EXPECT_TRUE(0 != vPtr)
<< "Unable to get pointer to main() from JIT";
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp
index e9cf904..43a8298 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp
+++ b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp
@@ -34,6 +34,7 @@ namespace {
/*
TEST_F(MCJITTest, empty_module) {
createJIT(M.take());
+ TheJIT->finalizeObject();
//EXPECT_NE(0, TheJIT->getObjectImage())
// << "Unable to generate executable loaded object image";
}
@@ -46,8 +47,7 @@ TEST_F(MCJITTest, global_variable) {
GlobalValue *Global = insertGlobalInt32(M.get(), "test_global", initialValue);
createJIT(M.take());
void *globalPtr = TheJIT->getPointerToGlobal(Global);
- MM->applyPermissions();
- static_cast<SectionMemoryManager*>(MM)->invalidateInstructionCache();
+ TheJIT->finalizeObject();
EXPECT_TRUE(0 != globalPtr)
<< "Unable to get pointer to global value from JIT";
@@ -61,8 +61,7 @@ TEST_F(MCJITTest, add_function) {
Function *F = insertAddFunction(M.get());
createJIT(M.take());
void *addPtr = TheJIT->getPointerToFunction(F);
- MM->applyPermissions();
- static_cast<SectionMemoryManager*>(MM)->invalidateInstructionCache();
+ TheJIT->finalizeObject();
EXPECT_TRUE(0 != addPtr)
<< "Unable to get pointer to function from JIT";
@@ -79,8 +78,7 @@ TEST_F(MCJITTest, run_main) {
Function *Main = insertMainFunction(M.get(), 6);
createJIT(M.take());
void *vPtr = TheJIT->getPointerToFunction(Main);
- MM->applyPermissions();
- static_cast<SectionMemoryManager*>(MM)->invalidateInstructionCache();
+ TheJIT->finalizeObject();
EXPECT_TRUE(0 != vPtr)
<< "Unable to get pointer to main() from JIT";
@@ -102,8 +100,7 @@ TEST_F(MCJITTest, return_global) {
createJIT(M.take());
void *rgvPtr = TheJIT->getPointerToFunction(ReturnGlobal);
- MM->applyPermissions();
- static_cast<SectionMemoryManager*>(MM)->invalidateInstructionCache();
+ TheJIT->finalizeObject();
EXPECT_TRUE(0 != rgvPtr);
int32_t(*FuncPtr)(void) = (int32_t(*)(void))(intptr_t)rgvPtr;
@@ -134,6 +131,7 @@ TEST_F(MCJITTest, increment_global) {
createJIT(M.take());
void *gvPtr = TheJIT->getPointerToGlobal(GV);
+ TheJIT->finalizeObject();
EXPECT_EQ(initialNum, *(int32_t*)gvPtr);
void *vPtr = TheJIT->getPointerToFunction(IncrementGlobal);
@@ -150,6 +148,9 @@ TEST_F(MCJITTest, increment_global) {
}
*/
+// PR16013: XFAIL this test on ARM, which currently can't handle multiple relocations.
+#if !defined(__arm__)
+
TEST_F(MCJITTest, multiple_functions) {
SKIP_UNSUPPORTED_PLATFORM;
@@ -172,8 +173,7 @@ TEST_F(MCJITTest, multiple_functions) {
createJIT(M.take());
void *vPtr = TheJIT->getPointerToFunction(Outer);
- MM->applyPermissions();
- static_cast<SectionMemoryManager*>(MM)->invalidateInstructionCache();
+ TheJIT->finalizeObject();
EXPECT_TRUE(0 != vPtr)
<< "Unable to get pointer to outer function from JIT";
@@ -182,6 +182,8 @@ TEST_F(MCJITTest, multiple_functions) {
<< "Incorrect result returned from function";
}
+#endif /*!defined(__arm__)*/
+
// FIXME: ExecutionEngine has no support empty modules
/*
TEST_F(MCJITTest, multiple_empty_modules) {
@@ -219,6 +221,7 @@ TEST_F(MCJITTest, multiple_modules) {
// get a function pointer in a module that was not used in EE construction
void *vPtr = TheJIT->getPointerToFunction(Caller);
+ TheJIT->finalizeObject();
EXPECT_NE(0, vPtr)
<< "Unable to get pointer to caller function from JIT";
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h
index 8160a18..7b6e39f 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h
+++ b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h
@@ -49,11 +49,23 @@ protected:
/// Returns true if the host architecture is known to support MCJIT
bool ArchSupportsMCJIT() {
Triple Host(HostTriple);
+ // If ARCH is not supported, bail
if (std::find(SupportedArchs.begin(), SupportedArchs.end(), Host.getArch())
- == SupportedArchs.end()) {
+ == SupportedArchs.end())
return false;
- }
- return true;
+
+ // If ARCH is supported and has no specific sub-arch support
+ if (std::find(HasSubArchs.begin(), HasSubArchs.end(), Host.getArch())
+ == HasSubArchs.end())
+ return true;
+
+ // If ARCH has sub-arch support, find it
+ SmallVectorImpl<std::string>::const_iterator I = SupportedSubArchs.begin();
+ for(; I != SupportedSubArchs.end(); ++I)
+ if (Host.getArchName().startswith(I->c_str()))
+ return true;
+
+ return false;
}
/// Returns true if the host OS is known to support MCJIT
@@ -68,6 +80,8 @@ protected:
std::string HostTriple;
SmallVector<Triple::ArchType, 4> SupportedArchs;
+ SmallVector<Triple::ArchType, 1> HasSubArchs;
+ SmallVector<std::string, 2> SupportedSubArchs; // We need to own the memory
SmallVector<Triple::OSType, 4> UnsupportedOSs;
};
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h
index b0e98a8..95a5c8b 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h
+++ b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h
@@ -44,11 +44,19 @@ protected:
// The architectures below are known to be compatible with MCJIT as they
// are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
// kept in sync.
+ SupportedArchs.push_back(Triple::aarch64);
SupportedArchs.push_back(Triple::arm);
SupportedArchs.push_back(Triple::mips);
SupportedArchs.push_back(Triple::x86);
SupportedArchs.push_back(Triple::x86_64);
+ // Some architectures have sub-architectures in which tests will fail, like
+ // ARM. These two vectors will define if they do have sub-archs (to avoid
+ // extra work for those who don't), and if so, if they are listed to work
+ HasSubArchs.push_back(Triple::arm);
+ SupportedSubArchs.push_back("armv6");
+ SupportedSubArchs.push_back("armv7");
+
// The operating systems below are known to be incompatible with MCJIT as
// they are copied from the test/ExecutionEngine/MCJIT/lit.local.cfg and
// should be kept in sync.
@@ -165,7 +173,7 @@ protected:
std::string Error;
TheJIT.reset(EB.setEngineKind(EngineKind::JIT)
.setUseMCJIT(true) /* can this be folded into the EngineKind enum? */
- .setJITMemoryManager(MM)
+ .setMCJITMemoryManager(MM)
.setErrorStr(&Error)
.setOptLevel(CodeGenOpt::None)
.setAllocateGVsWithCode(false) /*does this do anything?*/
@@ -185,10 +193,9 @@ protected:
CodeModel::Model CodeModel;
StringRef MArch;
SmallVector<std::string, 1> MAttrs;
- OwningPtr<TargetMachine> TM;
OwningPtr<ExecutionEngine> TheJIT;
IRBuilder<> Builder;
- JITMemoryManager *MM;
+ RTDyldMemoryManager *MM;
OwningPtr<Module> M;
};