"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
/// 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
/// 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;
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);
/// 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:
return (uint8_t*)DataAllocator.Allocate(Size, Alignment);
}
- bool applyPermissions(std::string *ErrMsg) {
+ bool finalizeMemory(std::string *ErrMsg) {
return false;
}
MemMgr->registerEHFrames(EHData);
// Set page permissions.
- MemMgr->applyPermissions();
+ MemMgr->finalizeMemory();
}
void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
/// 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);
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;
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.
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
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);
}
}\r
\r
std::string Error;\r
- EXPECT_FALSE(MemMgr->applyPermissions(&Error));\r
+ EXPECT_FALSE(MemMgr->finalizeMemory(&Error));\r
}\r
\r
TEST(MCJITMemoryManagerTest, LargeAllocations) {\r
}\r
\r
std::string Error;\r
- EXPECT_FALSE(MemMgr->applyPermissions(&Error));\r
+ EXPECT_FALSE(MemMgr->finalizeMemory(&Error));\r
}\r
\r
TEST(MCJITMemoryManagerTest, ManyAllocations) {\r
}\r
\r
std::string Error;\r
- EXPECT_FALSE(MemMgr->applyPermissions(&Error));\r
+ EXPECT_FALSE(MemMgr->finalizeMemory(&Error));\r
}\r
\r
TEST(MCJITMemoryManagerTest, ManyVariedAllocations) {\r
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";
/*
TEST_F(MCJITTest, empty_module) {
createJIT(M.take());
+ TheJIT->finalizeObject();
//EXPECT_NE(0, TheJIT->getObjectImage())
// << "Unable to generate executable loaded object image";
}
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";
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";
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";
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;
createJIT(M.take());
void *gvPtr = TheJIT->getPointerToGlobal(GV);
+ TheJIT->finalizeObject();
EXPECT_EQ(initialNum, *(int32_t*)gvPtr);
void *vPtr = TheJIT->getPointerToFunction(IncrementGlobal);
}
*/
+// PR16013: XFAIL this test on ARM, which currently can't handle multiple relocations.
+#if !defined(__arm__)
+
TEST_F(MCJITTest, multiple_functions) {
SKIP_UNSUPPORTED_PLATFORM;
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";
<< "Incorrect result returned from function";
}
+#endif /*!defined(__arm__)*/
+
// FIXME: ExecutionEngine has no support empty modules
/*
TEST_F(MCJITTest, multiple_empty_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";