summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/ExecutionEngine/ExecutionEngine.h13
-rw-r--r--include/llvm/ExecutionEngine/RuntimeDyld.h6
-rw-r--r--include/llvm/ExecutionEngine/SectionMemoryManager.h11
-rw-r--r--lib/ExecutionEngine/JIT/JITMemoryManager.cpp2
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJIT.cpp2
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJIT.h7
-rw-r--r--lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp2
-rw-r--r--tools/lli/RecordingMemoryManager.h2
-rw-r--r--tools/llvm-rtdyld/llvm-rtdyld.cpp2
-rw-r--r--unittests/ExecutionEngine/JIT/JITTest.cpp2
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp6
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp3
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITTest.cpp23
13 files changed, 48 insertions, 33 deletions
diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h
index 83a672de2b..ceac298655 100644
--- a/include/llvm/ExecutionEngine/ExecutionEngine.h
+++ b/include/llvm/ExecutionEngine/ExecutionEngine.h
@@ -252,11 +252,14 @@ public:
"EE!");
}
- // finalizeObject - This method should be called after sections within an
- // object have been relocated using mapSectionAddress. When this method is
- // called the MCJIT execution engine will reapply relocations for a loaded
- // object. This method has no effect for the legacy JIT engine or the
- // interpeter.
+ /// finalizeObject - ensure the module is fully processed and is usable.
+ ///
+ /// It is the user-level function for completing the process of making the
+ /// object usable for execution. It should be called after sections within an
+ /// object have been relocated using mapSectionAddress. When this method is
+ /// called the MCJIT execution engine will reapply relocations for a loaded
+ /// object. This method has no effect for the legacy JIT engine or the
+ /// interpeter.
virtual void finalizeObject() {}
/// runStaticConstructorsDestructors - This method is used to execute all of
diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h
index c6c126c6e2..7dba040961 100644
--- a/include/llvm/ExecutionEngine/RuntimeDyld.h
+++ b/include/llvm/ExecutionEngine/RuntimeDyld.h
@@ -62,10 +62,12 @@ public:
/// permissions can be applied. It is up to the memory manager implementation
/// to decide whether or not to act on this method. The memory manager will
/// typically allocate all sections as read-write and then apply specific
- /// permissions when this method is called.
+ /// permissions when this method is called. Code sections cannot be executed
+ /// until this function has been called. In addition, any cache coherency
+ /// operations needed to reliably use the memory are also performed.
///
/// Returns true if an error occurred, false otherwise.
- virtual bool applyPermissions(std::string *ErrMsg = 0) = 0;
+ virtual bool finalizeMemory(std::string *ErrMsg = 0) = 0;
/// Register the EH frames with the runtime so that c++ exceptions work. The
/// default implementation does nothing. Look at SectionMemoryManager for one
diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h
index 305a96619a..fc8dacfcc0 100644
--- a/include/llvm/ExecutionEngine/SectionMemoryManager.h
+++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h
@@ -33,7 +33,7 @@ namespace llvm {
/// Any client using this memory manager MUST ensure that section-specific
/// page permissions have been applied before attempting to execute functions
/// in the JITed object. Permissions can be applied either by calling
-/// MCJIT::finalizeObject or by calling SectionMemoryManager::applyPermissions
+/// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory
/// directly. Clients of MCJIT should call MCJIT::finalizeObject.
class SectionMemoryManager : public RTDyldMemoryManager {
SectionMemoryManager(const SectionMemoryManager&) LLVM_DELETED_FUNCTION;
@@ -60,17 +60,18 @@ public:
unsigned SectionID,
bool isReadOnly);
- /// \brief Applies section-specific memory permissions.
+ /// \brief Update section-specific memory permissions and other attributes.
///
/// This method is called when object loading is complete and section page
/// permissions can be applied. It is up to the memory manager implementation
/// to decide whether or not to act on this method. The memory manager will
/// typically allocate all sections as read-write and then apply specific
/// permissions when this method is called. Code sections cannot be executed
- /// until this function has been called.
+ /// until this function has been called. In addition, any cache coherency
+ /// operations needed to reliably use the memory are also performed.
///
/// \returns true if an error occurred, false otherwise.
- virtual bool applyPermissions(std::string *ErrMsg = 0);
+ virtual bool finalizeMemory(std::string *ErrMsg = 0);
void registerEHFrames(StringRef SectionData);
@@ -89,7 +90,7 @@ public:
/// explicit cache flush, otherwise JIT code manipulations (like resolved
/// relocations) will get to the data cache but not to the instruction cache.
///
- /// This method is called from applyPermissions.
+ /// This method is called from finalizeMemory.
virtual void invalidateInstructionCache();
private:
diff --git a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
index bf5680d832..6a1db16a6a 100644
--- a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
+++ b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
@@ -509,7 +509,7 @@ namespace {
return (uint8_t*)DataAllocator.Allocate(Size, Alignment);
}
- bool applyPermissions(std::string *ErrMsg) {
+ bool finalizeMemory(std::string *ErrMsg) {
return false;
}
diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp
index ced567205a..e861938563 100644
--- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp
+++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp
@@ -178,7 +178,7 @@ void MCJIT::finalizeObject() {
MemMgr->registerEHFrames(EHData);
// Set page permissions.
- MemMgr->applyPermissions();
+ MemMgr->finalizeMemory();
}
void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h
index 7f247e2dee..a899d4f408 100644
--- a/lib/ExecutionEngine/MCJIT/MCJIT.h
+++ b/lib/ExecutionEngine/MCJIT/MCJIT.h
@@ -52,6 +52,13 @@ public:
/// Sets the object manager that MCJIT should use to avoid compilation.
virtual void setObjectCache(ObjectCache *manager);
+ /// finalizeObject - ensure the module is fully processed and is usable.
+ ///
+ /// It is the user-level function for completing the process of making the
+ /// object usable for execution. It should be called after sections within an
+ /// object have been relocated using mapSectionAddress. When this method is
+ /// called the MCJIT execution engine will reapply relocations for a loaded
+ /// object.
virtual void finalizeObject();
virtual void *getPointerToBasicBlock(BasicBlock *BB);
diff --git a/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp b/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp
index bac77ce75f..1bb0103f08 100644
--- a/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp
+++ b/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp
@@ -111,7 +111,7 @@ uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup,
return (uint8_t*)Addr;
}
-bool SectionMemoryManager::applyPermissions(std::string *ErrMsg)
+bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg)
{
// FIXME: Should in-progress permissions be reverted if an error occurs?
error_code ec;
diff --git a/tools/lli/RecordingMemoryManager.h b/tools/lli/RecordingMemoryManager.h
index f3d026f241..b2919c3979 100644
--- a/tools/lli/RecordingMemoryManager.h
+++ b/tools/lli/RecordingMemoryManager.h
@@ -58,7 +58,7 @@ public:
void *getPointerToNamedFunction(const std::string &Name,
bool AbortOnFailure = true);
- bool applyPermissions(std::string *ErrMsg) { return false; }
+ bool finalizeMemory(std::string *ErrMsg) { return false; }
// The following obsolete JITMemoryManager calls are stubbed out for
// this model.
diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp
index ead541a5b8..b68f2a08d9 100644
--- a/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -69,7 +69,7 @@ public:
return 0;
}
- bool applyPermissions(std::string *ErrMsg) { return false; }
+ bool finalizeMemory(std::string *ErrMsg) { return false; }
// Invalidate instruction cache for sections with execute permissions.
// Some platforms with separate data cache and instruction cache require
diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp
index cf995aac7a..f8d9da2755 100644
--- a/unittests/ExecutionEngine/JIT/JITTest.cpp
+++ b/unittests/ExecutionEngine/JIT/JITTest.cpp
@@ -127,7 +127,7 @@ public:
unsigned SectionID) {
return Base->allocateCodeSection(Size, Alignment, SectionID);
}
- virtual bool applyPermissions(std::string *ErrMsg) { return false; }
+ virtual bool finalizeMemory(std::string *ErrMsg) { return false; }
virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
return Base->allocateSpace(Size, Alignment);
}
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp
index ab09acad0d..9e0b35395e 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 abe8be450a..32fc292496 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp
+++ b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp
@@ -101,11 +101,10 @@ protected:
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 e9cf904b18..43a82984c4 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";