From ccbb603f3183c6e87898c5d5e3eb1ecf1328ea72 Mon Sep 17 00:00:00 2001 From: David Tweed Date: Fri, 17 May 2013 10:01:46 +0000 Subject: [PATCH] Minor changes to the MCJITTest unittests to use the correct API for finalizing the JIT object (including XFAIL an ARM test that now needs fixing). Also renames internal function for consistency. llvm-svn: 182085 --- .../llvm/ExecutionEngine/ExecutionEngine.h | 13 +++++++---- include/llvm/ExecutionEngine/RuntimeDyld.h | 6 +++-- .../ExecutionEngine/SectionMemoryManager.h | 11 +++++---- lib/ExecutionEngine/JIT/JITMemoryManager.cpp | 2 +- lib/ExecutionEngine/MCJIT/MCJIT.cpp | 2 +- lib/ExecutionEngine/MCJIT/MCJIT.h | 7 ++++++ .../MCJIT/SectionMemoryManager.cpp | 2 +- tools/lli/RecordingMemoryManager.h | 2 +- tools/llvm-rtdyld/llvm-rtdyld.cpp | 2 +- unittests/ExecutionEngine/JIT/JITTest.cpp | 2 +- .../MCJIT/MCJITMemoryManagerTest.cpp | 6 ++--- .../MCJIT/MCJITObjectCacheTest.cpp | 3 +-- unittests/ExecutionEngine/MCJIT/MCJITTest.cpp | 23 +++++++++++-------- 13 files changed, 48 insertions(+), 33 deletions(-) diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 83a672de2b6..ceac298655e 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 c6c126c6e24..7dba040961a 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 305a96619a0..fc8dacfcc09 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 bf5680d832d..6a1db16a6a1 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 ced567205aa..e8619385635 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 7f247e2dee5..a899d4f4080 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 bac77ce75f4..1bb0103f08e 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 f3d026f2419..b2919c39790 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 ead541a5b80..b68f2a08d92 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 cf995aac7a1..f8d9da27550 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 ab09acad0d3..9e0b35395e5 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 abe8be450ae..32fc292496c 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(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 e9cf904b181..43a82984c45 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(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(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(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(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(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";