diff --git a/include/llvm/System/Memory.h b/include/llvm/System/Memory.h index 52e1f3f14b7..014633c8c55 100644 --- a/include/llvm/System/Memory.h +++ b/include/llvm/System/Memory.h @@ -39,33 +39,36 @@ namespace sys { /// @since 1.4 /// @brief An abstraction for memory operations. class Memory { - /// @name Functions - /// @{ - public: - /// This method allocates a block of Read/Write/Execute memory that is - /// suitable for executing dynamically generated code (e.g. JIT). An - /// attempt to allocate \p NumBytes bytes of virtual memory is made. - /// \p NearBlock may point to an existing allocation in which case - /// an attempt is made to allocate more memory near the existing block. - /// - /// On success, this returns a non-null memory block, otherwise it returns - /// a null memory block and fills in *ErrMsg. - /// - /// @brief Allocate Read/Write/Execute memory. - static MemoryBlock AllocateRWX(unsigned NumBytes, - const MemoryBlock *NearBlock, - std::string *ErrMsg = 0); + public: + /// This method allocates a block of Read/Write/Execute memory that is + /// suitable for executing dynamically generated code (e.g. JIT). An + /// attempt to allocate \p NumBytes bytes of virtual memory is made. + /// \p NearBlock may point to an existing allocation in which case + /// an attempt is made to allocate more memory near the existing block. + /// + /// On success, this returns a non-null memory block, otherwise it returns + /// a null memory block and fills in *ErrMsg. + /// + /// @brief Allocate Read/Write/Execute memory. + static MemoryBlock AllocateRWX(unsigned NumBytes, + const MemoryBlock *NearBlock, + std::string *ErrMsg = 0); - /// This method releases a block of Read/Write/Execute memory that was - /// allocated with the AllocateRWX method. It should not be used to - /// release any memory block allocated any other way. - /// - /// On success, this returns false, otherwise it returns true and fills - /// in *ErrMsg. - /// @throws std::string if an error occurred. - /// @brief Release Read/Write/Execute memory. - static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = 0); - /// @} + /// This method releases a block of Read/Write/Execute memory that was + /// allocated with the AllocateRWX method. It should not be used to + /// release any memory block allocated any other way. + /// + /// On success, this returns false, otherwise it returns true and fills + /// in *ErrMsg. + /// @throws std::string if an error occurred. + /// @brief Release Read/Write/Execute memory. + static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = 0); + + + /// InvalidateInstructionCache - Before the JIT can run a block of code + /// that has been emitted it must invalidate the instruction cache on some + /// platforms. + static void InvalidateInstructionCache(const void *Addr, size_t Len); }; } } diff --git a/lib/System/Memory.cpp b/lib/System/Memory.cpp index 054cc966a3e..bbb7917dca3 100644 --- a/lib/System/Memory.cpp +++ b/lib/System/Memory.cpp @@ -17,12 +17,6 @@ namespace llvm { using namespace sys; - -//===----------------------------------------------------------------------===// -//=== WARNING: Implementation here must contain only TRULY operating system -//=== independent code. -//===----------------------------------------------------------------------===// - } // Include the platform-specific parts of this class. @@ -32,3 +26,34 @@ using namespace sys; #ifdef LLVM_ON_WIN32 #include "Win32/Memory.inc" #endif + +/// InvalidateInstructionCache - Before the JIT can run a block of code +/// that has been emitted it must invalidate the instruction cache on some +/// platforms. +void llvm::sys::Memory::InvalidateInstructionCache(const void *Addr, + size_t Len) { + +// icache invalidation for PPC. +#if (defined(__POWERPC__) || defined (__ppc__) || \ + defined(_POWER) || defined(_ARCH_PPC)) + #if defined(__APPLE__) + extern "C" void sys_icache_invalidate(const void *Addr, size_t len); + sys_icache_invalidate(Addr, len); + #elif defined(__GNUC__) + const size_t LineSize = 32; + + const intptr_t Mask = ~(LineSize - 1); + const intptr_t StartLine = ((intptr_t) Addr) & Mask; + const intptr_t EndLine = ((intptr_t) Addr + len + LineSize - 1) & Mask; + + for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) + asm volatile("dcbf 0, %0" : : "r"(Line)); + asm volatile("sync"); + + for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) + asm volatile("icbi 0, %0" : : "r"(Line)); + asm volatile("isync"); + #endif +#endif // end PPC + +} \ No newline at end of file