[llvm-commits] [llvm] r168721 - in /llvm/trunk: include/llvm/ExecutionEngine/SectionMemoryManager.h lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt lib/ExecutionEngine/RuntimeDyld/SectionMemoryManager.cpp unittests/ExecutionEngine/MCJIT/CMakeLists.t...

Kaylor, Andrew andrew.kaylor at intel.com
Tue Nov 27 12:41:04 PST 2012


Hmmm.... JIT isn't supposed to depend on RuntimeDyld.  The RuntimeDyldMemoryManager really should be a pure virtual base class.  It was introduced so that it would be easier for the legacy JIT stuff to fall away in the future.  Also, SectionMemoryManager only derives from JITMemoryManager because the ExecutionEngine interface requires it.  JITMemoryManager should be pure virtual too.

I'll look into this and figure out the best way to resolve the dependencies.

-Andy

-----Original Message-----
From: Benjamin Kramer [mailto:benny.kra at gmail.com] 
Sent: Tuesday, November 27, 2012 12:18 PM
To: Kaylor, Andrew
Cc: llvm-commits at cs.uiuc.edu
Subject: Re: [llvm-commits] [llvm] r168721 - in /llvm/trunk: include/llvm/ExecutionEngine/SectionMemoryManager.h lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt lib/ExecutionEngine/RuntimeDyld/SectionMemoryManager.cpp unittests/ExecutionEngine/MCJIT/CMakeLists.t...


On 27.11.2012, at 20:42, Andrew Kaylor <andrew.kaylor at intel.com> wrote:

> Author: akaylor
> Date: Tue Nov 27 13:42:02 2012
> New Revision: 168721
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=168721&view=rev
> Log:
> Moving SectionMemoryManager into RuntimeDyld and adding unit tests for it.
> 
> The SectionMemoryManager now supports (and requires) applying section-specific page permissions.  Clients using this memory manager must call either MCJIT::finalizeObject() or SectionMemoryManager::applyPermissions() before executing JITed code.
> 
> See r168718 for changes from the previous implementation.
> 
> Added:
>    llvm/trunk/include/llvm/ExecutionEngine/SectionMemoryManager.h
>    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/SectionMemoryManager.cpp
>    
> llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp
> Removed:
>    llvm/trunk/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.cpp
>    llvm/trunk/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.h
> Modified:
>    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
>    llvm/trunk/unittests/ExecutionEngine/MCJIT/CMakeLists.txt
>    llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h
> 
> Added: llvm/trunk/include/llvm/ExecutionEngine/SectionMemoryManager.h
> URL: 
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionE
> ngine/SectionMemoryManager.h?rev=168721&view=auto
> ======================================================================
> ========
> --- llvm/trunk/include/llvm/ExecutionEngine/SectionMemoryManager.h 
> (added)
> +++ llvm/trunk/include/llvm/ExecutionEngine/SectionMemoryManager.h Tue 
> +++ Nov 27 13:42:02 2012
> @@ -0,0 +1,176 @@
> +//===- SectionMemoryManager.h - Memory manager for MCJIT/RtDyld -*- 
> +C++ -*-===// //
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open 
> +Source // License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------
> +------===//
> +//
> +// This file contains the declaration of a section-based memory 
> +manager used by // the MCJIT execution engine and RuntimeDyld.
> +//
> +//===----------------------------------------------------------------
> +------===//
> +
> +#ifndef LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H
> +#define LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H
> +
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/ExecutionEngine/JITMemoryManager.h"
> +#include "llvm/Support/ErrorHandling.h"
> +#include "llvm/Support/Memory.h"
> +
> +namespace llvm {
> +
> +/// This is a simple memory manager which implements the methods 
> +called by /// the RuntimeDyld class to allocate memory for 
> +section-based loading of /// objects, usually those generated by the MCJIT execution engine.
> +///
> +/// This memory manager allocates all section memory as read-write.  
> +The /// RuntimeDyld will copy JITed section memory into these 
> +allocated blocks /// and perform any necessary linking and relocations.
> +///
> +/// 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
> +/// directly.  Clients of MCJIT should call MCJIT::finalizeObject.
> +class SectionMemoryManager : public JITMemoryManager {

This adds a cyclic dependency from RuntimeDyld to JIT. Can JITMemoryManager also be moved from JIT to RuntimeDyld?

- Ben

> +  SectionMemoryManager(const SectionMemoryManager&) 
> + LLVM_DELETED_FUNCTION;  void operator=(const SectionMemoryManager&) 
> + LLVM_DELETED_FUNCTION;
> +
> +public:
> +  SectionMemoryManager() { }
> +  virtual ~SectionMemoryManager();
> +
> +  /// \brief Allocates a memory block of (at least) the given size 
> + suitable for  /// executable code.
> +  ///
> +  /// The value of \p Alignment must be a power of two.  If \p 
> + Alignment is zero  /// a default alignment of 16 will be used.
> +  virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
> +                                       unsigned SectionID);
> +
> +  /// \brief Allocates a memory block of (at least) the given size 
> + suitable for  /// executable code.
> +  ///
> +  /// The value of \p Alignment must be a power of two.  If \p 
> + Alignment is zero  /// a default alignment of 16 will be used.
> +  virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
> +                                       unsigned SectionID,
> +                                       bool isReadOnly);
> +
> +  /// \brief Applies section-specific memory permissions.
> +  ///
> +  /// 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.
> +  ///
> +  /// \returns true if an error occurred, false otherwise.
> +  virtual bool applyPermissions(std::string *ErrMsg = 0);
> +
> +  /// This method returns the address of the specified function. As 
> + such it is  /// only useful for resolving library symbols, not code generated symbols.
> +  ///
> +  /// If \p AbortOnFailure is false and no function with the given 
> + name is  /// found, this function returns a null pointer. Otherwise, 
> + it prints a  /// message to stderr and aborts.
> +  virtual void *getPointerToNamedFunction(const std::string &Name,
> +                                          bool AbortOnFailure = 
> + true);
> +
> +  /// \brief Invalidate instruction cache for code sections.
> +  ///
> +  /// Some platforms with separate data cache and instruction cache 
> + require  /// 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 not called by RuntimeDyld or MCJIT during the 
> + load  /// process.  Clients may call this function when needed.  See 
> + the lli  /// tool for example use.
> +  virtual void invalidateInstructionCache();
> +
> +private:
> +  struct MemoryGroup {
> +      SmallVector<sys::MemoryBlock, 16> AllocatedMem;
> +      SmallVector<sys::MemoryBlock, 16> FreeMem;
> +      sys::MemoryBlock Near;
> +  };
> +
> +  uint8_t *allocateSection(MemoryGroup &MemGroup, uintptr_t Size,
> +                           unsigned Alignment);
> +
> +  error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup,
> +                                         unsigned Permissions);
> +
> +  MemoryGroup CodeMem;
> +  MemoryGroup RWDataMem;
> +  MemoryGroup RODataMem;
> +
> +public:
> +  ///
> +  /// Functions below are not used by MCJIT or RuntimeDyld, but must 
> +be
> +  /// implemented because they are declared as pure virtuals in the base class.
> +  ///
> +
> +  virtual void setMemoryWritable() {
> +    llvm_unreachable("Unexpected call!");
> +  }
> +  virtual void setMemoryExecutable() {
> +    llvm_unreachable("Unexpected call!");
> +  }
> +  virtual void setPoisonMemory(bool poison) {
> +    llvm_unreachable("Unexpected call!");
> +  }
> +  virtual void AllocateGOT() {
> +    llvm_unreachable("Unexpected call!");
> +  }
> +  virtual uint8_t *getGOTBase() const {
> +    llvm_unreachable("Unexpected call!");
> +    return 0;
> +  }
> +  virtual uint8_t *startFunctionBody(const Function *F,
> +                                     uintptr_t &ActualSize){
> +    llvm_unreachable("Unexpected call!");
> +    return 0;
> +  }
> +  virtual uint8_t *allocateStub(const GlobalValue *F, unsigned StubSize,
> +                                unsigned Alignment) {
> +    llvm_unreachable("Unexpected call!");
> +    return 0;
> +  }
> +  virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart,
> +                               uint8_t *FunctionEnd) {
> +    llvm_unreachable("Unexpected call!");
> +  }
> +  virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
> +    llvm_unreachable("Unexpected call!");
> +    return 0;
> +  }
> +  virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
> +    llvm_unreachable("Unexpected call!");
> +    return 0;
> +  }
> +  virtual void deallocateFunctionBody(void *Body) {
> +    llvm_unreachable("Unexpected call!");
> +  }
> +  virtual uint8_t *startExceptionTable(const Function *F,
> +                                       uintptr_t &ActualSize) {
> +    llvm_unreachable("Unexpected call!");
> +    return 0;
> +  }
> +  virtual void endExceptionTable(const Function *F, uint8_t *TableStart,
> +                                 uint8_t *TableEnd, uint8_t *FrameRegister) {
> +    llvm_unreachable("Unexpected call!");
> +  }
> +  virtual void deallocateExceptionTable(void *ET) {
> +    llvm_unreachable("Unexpected call!");
> +  }
> +};
> +
> +}
> +
> +#endif // LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H
> +
> 
> Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
> URL: 
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Run
> timeDyld/CMakeLists.txt?rev=168721&r1=168720&r2=168721&view=diff
> ======================================================================
> ========
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt 
> (original)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt Tue Nov 
> +++ 27 13:42:02 2012
> @@ -3,4 +3,5 @@
>   RuntimeDyld.cpp
>   RuntimeDyldELF.cpp
>   RuntimeDyldMachO.cpp
> +  SectionMemoryManager.cpp
>   )
> 
> Added: 
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/SectionMemoryManager.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Run
> timeDyld/SectionMemoryManager.cpp?rev=168721&view=auto
> ======================================================================
> ========
> --- 
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/SectionMemoryManager.cpp 
> (added)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/SectionMemoryManager.cp
> +++ p Tue Nov 27 13:42:02 2012
> @@ -0,0 +1,226 @@
> +//===- SectionMemoryManager.cpp - Memory manager for MCJIT/RtDyld *- 
> +C++ -*-==// //
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open 
> +Source // License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------
> +------===//
> +//
> +// This file implements the section-based memory manager used by the 
> +MCJIT // execution engine and RuntimeDyld // 
> +//===----------------------------------------------------------------
> +------===//
> +
> +#include "llvm/Config/config.h"
> +#include "llvm/ExecutionEngine/SectionMemoryManager.h"
> +#include "llvm/Support/DynamicLibrary.h"
> +#include "llvm/Support/MathExtras.h"
> +
> +#ifdef __linux__
> +  // These includes used by 
> +SectionMemoryManager::getPointerToNamedFunction()
> +  // for Glibc trickery. See comments in this function for more information.
> +  #ifdef HAVE_SYS_STAT_H
> +    #include <sys/stat.h>
> +  #endif
> +  #include <fcntl.h>
> +  #include <unistd.h>
> +#endif
> +
> +namespace llvm {
> +
> +uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size,
> +                                                    unsigned Alignment,
> +                                                    unsigned SectionID,
> +                                                    bool IsReadOnly) 
> +{
> +  if (IsReadOnly)
> +    return allocateSection(RODataMem, Size, Alignment);
> +  return allocateSection(RWDataMem, Size, Alignment); }
> +
> +uint8_t *SectionMemoryManager::allocateCodeSection(uintptr_t Size,
> +                                                   unsigned Alignment,
> +                                                   unsigned 
> +SectionID) {
> +  return allocateSection(CodeMem, Size, Alignment); }
> +
> +uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup,
> +                                               uintptr_t Size,
> +                                               unsigned Alignment) {
> +  if (!Alignment)
> +    Alignment = 16;
> +
> +  assert(!(Alignment & (Alignment - 1)) && "Alignment must be a power 
> + of two.");
> +
> +  uintptr_t RequiredSize = Alignment * ((Size + Alignment - 
> + 1)/Alignment + 1);  uintptr_t Addr = 0;
> +
> +  // Look in the list of free memory regions and use a block there if 
> + one  // is available.
> +  for (int i = 0, e = MemGroup.FreeMem.size(); i != e; ++i) {
> +    sys::MemoryBlock &MB = MemGroup.FreeMem[i];
> +    if (MB.size() >= RequiredSize) {
> +      Addr = (uintptr_t)MB.base();
> +      uintptr_t EndOfBlock = Addr + MB.size();
> +      // Align the address.
> +      Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
> +      // Store cutted free memory block.
> +      MemGroup.FreeMem[i] = sys::MemoryBlock((void*)(Addr + Size),
> +                                             EndOfBlock - Addr - Size);
> +      return (uint8_t*)Addr;
> +    }
> +  }
> +
> +  // No pre-allocated free block was large enough. Allocate a new memory region.
> +  // Note that all sections get allocated as read-write.  The 
> + permissions will  // be updated later based on memory group.
> +  //
> +  // FIXME: It would be useful to define a default allocation size 
> + (or add  // it as a constructor parameter) to minimize the number of allocations.
> +  //
> +  // FIXME: Initialize the Near member for each memory group to avoid  
> + // interleaving.
> +  error_code ec;
> +  sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(RequiredSize,
> +                                                          &MemGroup.Near,
> +                                                          sys::Memory::MF_READ |
> +                                                            sys::Memory::MF_WRITE,
> +                                                          ec);  if 
> + (ec) {
> +    // FIXME: Add error propogation to the interface.
> +    return NULL;
> +  }
> +
> +  // Save this address as the basis for our next request  
> + MemGroup.Near = MB;
> +
> +  MemGroup.AllocatedMem.push_back(MB);
> +  Addr = (uintptr_t)MB.base();
> +  uintptr_t EndOfBlock = Addr + MB.size();
> +
> +  // Align the address.
> +  Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
> +
> +  // The allocateMappedMemory may allocate much more memory than we 
> + need. In  // this case, we store the unused memory as a free memory block.
> +  unsigned FreeSize = EndOfBlock-Addr-Size;  if (FreeSize > 16)
> +    MemGroup.FreeMem.push_back(sys::MemoryBlock((void*)(Addr + Size), 
> + FreeSize));
> +
> +  // Return aligned address
> +  return (uint8_t*)Addr;
> +}
> +
> +bool SectionMemoryManager::applyPermissions(std::string *ErrMsg) {
> +  // FIXME: Should in-progress permissions be reverted if an error occurs?
> +  error_code ec;
> +
> +  // Make code memory executable.
> +  ec = applyMemoryGroupPermissions(CodeMem,
> +                                   sys::Memory::MF_READ | 
> + sys::Memory::MF_EXEC);  if (ec) {
> +    if (ErrMsg) {
> +      *ErrMsg = ec.message();
> +    }
> +    return true;
> +  }
> +
> +  // Make read-only data memory read-only.
> +  ec = applyMemoryGroupPermissions(RODataMem,
> +                                   sys::Memory::MF_READ | 
> + sys::Memory::MF_EXEC);  if (ec) {
> +    if (ErrMsg) {
> +      *ErrMsg = ec.message();
> +    }
> +    return true;
> +  }
> +
> +  // Read-write data memory already has the correct permissions
> +
> +  return false;
> +}
> +
> +error_code SectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup,
> +                                                             unsigned 
> +Permissions) {
> +
> +  for (int i = 0, e = MemGroup.AllocatedMem.size(); i != e; ++i) {
> +      error_code ec;
> +      ec = sys::Memory::protectMappedMemory(MemGroup.AllocatedMem[i],
> +                                            Permissions);
> +      if (ec) {
> +        return ec;
> +      }
> +  }
> +
> +  return error_code::success();
> +}
> +
> +void SectionMemoryManager::invalidateInstructionCache() {
> +  for (int i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i)
> +    sys::Memory::InvalidateInstructionCache(CodeMem.AllocatedMem[i].base(),
> +                                            
> +CodeMem.AllocatedMem[i].size()); }
> +
> +static int jit_noop() {
> +  return 0;
> +}
> +
> +void *SectionMemoryManager::getPointerToNamedFunction(const std::string &Name,
> +                                                       bool 
> +AbortOnFailure) { #if defined(__linux__)
> +  
> +//===----------------------------------------------------------------
> +----===//
> +  // Function stubs that are invoked instead of certain library calls
> +  //
> +  // Force the following functions to be linked in to anything that 
> +uses the
> +  // JIT. This is a hack designed to work around the all-too-clever 
> +Glibc
> +  // strategy of making these functions work differently when inlined 
> +vs. when
> +  // not inlined, and hiding their real definitions in a separate 
> +archive file
> +  // that the dynamic linker can't see. For more info, search for
> +  // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
> +  if (Name == "stat") return (void*)(intptr_t)&stat;
> +  if (Name == "fstat") return (void*)(intptr_t)&fstat;
> +  if (Name == "lstat") return (void*)(intptr_t)&lstat;
> +  if (Name == "stat64") return (void*)(intptr_t)&stat64;
> +  if (Name == "fstat64") return (void*)(intptr_t)&fstat64;
> +  if (Name == "lstat64") return (void*)(intptr_t)&lstat64;
> +  if (Name == "atexit") return (void*)(intptr_t)&atexit;
> +  if (Name == "mknod") return (void*)(intptr_t)&mknod; #endif // 
> +__linux__
> +
> +  // We should not invoke parent's ctors/dtors from generated main()!
> +  // On Mingw and Cygwin, the symbol __main is resolved to  // 
> + callee's(eg. tools/lli) one, to invoke wrong duplicated ctors  // 
> + (and register wrong callee's dtors with atexit(3)).
> +  // We expect ExecutionEngine::runStaticConstructorsDestructors()
> +  // is called before ExecutionEngine::runFunctionAsMain() is called.
> +  if (Name == "__main") return (void*)(intptr_t)&jit_noop;
> +
> +  const char *NameStr = Name.c_str();  void *Ptr = 
> + sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
> +  if (Ptr) return Ptr;
> +
> +  // If it wasn't found and if it starts with an underscore ('_') 
> + character,  // try again without the underscore.
> +  if (NameStr[0] == '_') {
> +    Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
> +    if (Ptr) return Ptr;
> +  }
> +
> +  if (AbortOnFailure)
> +    report_fatal_error("Program used external function '" + Name +
> +                      "' which could not be resolved!");
> +  return 0;
> +}
> +
> +SectionMemoryManager::~SectionMemoryManager() {
> +  for (unsigned i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i)
> +    sys::Memory::releaseMappedMemory(CodeMem.AllocatedMem[i]);
> +  for (unsigned i = 0, e = RWDataMem.AllocatedMem.size(); i != e; ++i)
> +    sys::Memory::releaseMappedMemory(RWDataMem.AllocatedMem[i]);
> +  for (unsigned i = 0, e = RODataMem.AllocatedMem.size(); i != e; ++i)
> +    sys::Memory::releaseMappedMemory(RODataMem.AllocatedMem[i]);
> +}
> +
> +} // namespace llvm
> +
> 
> Modified: llvm/trunk/unittests/ExecutionEngine/MCJIT/CMakeLists.txt
> URL: 
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngi
> ne/MCJIT/CMakeLists.txt?rev=168721&r1=168720&r2=168721&view=diff
> ======================================================================
> ========
> --- llvm/trunk/unittests/ExecutionEngine/MCJIT/CMakeLists.txt 
> (original)
> +++ llvm/trunk/unittests/ExecutionEngine/MCJIT/CMakeLists.txt Tue Nov 
> +++ 27 13:42:02 2012
> @@ -2,14 +2,14 @@
>   asmparser
>   bitreader
>   bitwriter
> -  mcjit
>   jit
> +  mcjit
>   nativecodegen
>   )
> 
> set(MCJITTestsSources
>   MCJITTest.cpp
> -  SectionMemoryManager.cpp
> +  MCJITMemoryManagerTest.cpp
>   )
> 
> if(MSVC)
> 
> Added: 
> llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngi
> ne/MCJIT/MCJITMemoryManagerTest.cpp?rev=168721&view=auto
> ======================================================================
> ========
> --- 
> llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp 
> (added)
> +++ llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.
> +++ cpp Tue Nov 27 13:42:02 2012
> @@ -0,0 +1,172 @@
> +//===- MCJITMemoryManagerTest.cpp - Unit tests for the JIT memory 
> +manager -===// //
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open 
> +Source // License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------
> +------===//
> +
> +#include "gtest/gtest.h"
> +#include "llvm/ADT/OwningPtr.h"
> +#include "llvm/ExecutionEngine/SectionMemoryManager.h"
> +#include "llvm/ExecutionEngine/JIT.h"
> +
> +using namespace llvm;
> +
> +namespace {
> +
> +TEST(MCJITMemoryManagerTest, BasicAllocations) {
> +  OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager());
> +
> +  uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1);  uint8_t 
> + *data1 = MemMgr->allocateDataSection(256, 0, 2, true);  uint8_t 
> + *code2 = MemMgr->allocateCodeSection(256, 0, 3);  uint8_t *data2 = 
> + MemMgr->allocateDataSection(256, 0, 4, false);
> +
> +  EXPECT_NE((uint8_t*)0, code1);
> +  EXPECT_NE((uint8_t*)0, code2);
> +  EXPECT_NE((uint8_t*)0, data1);
> +  EXPECT_NE((uint8_t*)0, data2);
> +
> +  // Initialize the data
> +  for (unsigned i = 0; i < 256; ++i) {
> +    code1[i] = 1;
> +    code2[i] = 2;
> +    data1[i] = 3;
> +    data2[i] = 4;
> +  }
> +
> +  // Verify the data (this is checking for overlaps in the addresses)  
> + for (unsigned i = 0; i < 256; ++i) {
> +    EXPECT_EQ(1, code1[i]);
> +    EXPECT_EQ(2, code2[i]);
> +    EXPECT_EQ(3, data1[i]);
> +    EXPECT_EQ(4, data2[i]);
> +  }
> +
> +  std::string Error;
> +  EXPECT_FALSE(MemMgr->applyPermissions(&Error));
> +}
> +
> +TEST(MCJITMemoryManagerTest, LargeAllocations) {
> +  OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager());
> +
> +  uint8_t *code1 = MemMgr->allocateCodeSection(0x100000, 0, 1);  
> + uint8_t *data1 = MemMgr->allocateDataSection(0x100000, 0, 2, true);  
> + uint8_t *code2 = MemMgr->allocateCodeSection(0x100000, 0, 3);  
> + uint8_t *data2 = MemMgr->allocateDataSection(0x100000, 0, 4, false);
> +
> +  EXPECT_NE((uint8_t*)0, code1);
> +  EXPECT_NE((uint8_t*)0, code2);
> +  EXPECT_NE((uint8_t*)0, data1);
> +  EXPECT_NE((uint8_t*)0, data2);
> +
> +  // Initialize the data
> +  for (unsigned i = 0; i < 0x100000; ++i) {
> +    code1[i] = 1;
> +    code2[i] = 2;
> +    data1[i] = 3;
> +    data2[i] = 4;
> +  }
> +
> +  // Verify the data (this is checking for overlaps in the addresses)  
> + for (unsigned i = 0; i < 0x100000; ++i) {
> +    EXPECT_EQ(1, code1[i]);
> +    EXPECT_EQ(2, code2[i]);
> +    EXPECT_EQ(3, data1[i]);
> +    EXPECT_EQ(4, data2[i]);
> +  }
> +
> +  std::string Error;
> +  EXPECT_FALSE(MemMgr->applyPermissions(&Error));
> +}
> +
> +TEST(MCJITMemoryManagerTest, ManyAllocations) {
> +  OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager());
> +
> +  uint8_t* code[10000];
> +  uint8_t* data[10000];
> +
> +  for (unsigned i = 0; i < 10000; ++i) {
> +    const bool isReadOnly = i % 2 == 0;
> +
> +    code[i] = MemMgr->allocateCodeSection(32, 0, 1);
> +    data[i] = MemMgr->allocateDataSection(32, 0, 2, isReadOnly);
> +
> +    for (unsigned j = 0; j < 32; j++) {
> +      code[i][j] = 1 + (i % 254);
> +      data[i][j] = 2 + (i % 254);
> +    }
> +
> +    EXPECT_NE((uint8_t *)0, code[i]);
> +    EXPECT_NE((uint8_t *)0, data[i]);  }
> +
> +  // Verify the data (this is checking for overlaps in the addresses)  
> + for (unsigned i = 0; i < 10000; ++i) {
> +    for (unsigned j = 0; j < 32;j++ ) {
> +      uint8_t ExpectedCode = 1 + (i % 254);
> +      uint8_t ExpectedData = 2 + (i % 254);
> +      EXPECT_EQ(ExpectedCode, code[i][j]);
> +      EXPECT_EQ(ExpectedData, data[i][j]);
> +    }
> +  }
> +
> +  std::string Error;
> +  EXPECT_FALSE(MemMgr->applyPermissions(&Error));
> +}
> +
> +TEST(MCJITMemoryManagerTest, ManyVariedAllocations) {
> +  OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager());
> +
> +  uint8_t* code[10000];
> +  uint8_t* data[10000];
> +
> +  for (unsigned i = 0; i < 10000; ++i) {
> +    uintptr_t CodeSize = i % 16 + 1;
> +    uintptr_t DataSize = i % 8 + 1;
> +
> +    bool isReadOnly = i % 3 == 0;
> +    unsigned Align = 8 << (i % 4);
> +
> +    code[i] = MemMgr->allocateCodeSection(CodeSize, Align, i);
> +    data[i] = MemMgr->allocateDataSection(DataSize, Align, i + 10000,
> +                                          isReadOnly);
> +
> +    for (unsigned j = 0; j < CodeSize; j++) {
> +      code[i][j] = 1 + (i % 254);
> +    }
> +
> +    for (unsigned j = 0; j < DataSize; j++) {
> +      data[i][j] = 2 + (i % 254);
> +    }
> +
> +    EXPECT_NE((uint8_t *)0, code[i]);
> +    EXPECT_NE((uint8_t *)0, data[i]);
> +
> +    uintptr_t CodeAlign = Align ? (uintptr_t)code[i] % Align : 0;
> +    uintptr_t DataAlign = Align ? (uintptr_t)data[i] % Align : 0;
> +
> +    EXPECT_EQ((uintptr_t)0, CodeAlign);
> +    EXPECT_EQ((uintptr_t)0, DataAlign);  }
> +
> +  for (unsigned i = 0; i < 10000; ++i) {
> +    uintptr_t CodeSize = i % 16 + 1;
> +    uintptr_t DataSize = i % 8 + 1;
> +
> +    for (unsigned j = 0; j < CodeSize; j++) {
> +      uint8_t ExpectedCode = 1 + (i % 254);
> +      EXPECT_EQ(ExpectedCode, code[i][j]);
> +    }
> +
> +    for (unsigned j = 0; j < DataSize; j++) {
> +      uint8_t ExpectedData = 2 + (i % 254);
> +      EXPECT_EQ(ExpectedData, data[i][j]); 
> +    }
> +  }
> +}
> +
> +} // Namespace
> +
> 
> Modified: llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h
> URL: 
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngi
> ne/MCJIT/MCJITTestBase.h?rev=168721&r1=168720&r2=168721&view=diff
> ======================================================================
> ========
> --- llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h 
> (original)
> +++ llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h Tue Nov 
> +++ 27 13:42:02 2012
> @@ -21,6 +21,7 @@
> #include "llvm/ADT/SmallVector.h"
> #include "llvm/Config/config.h"
> #include "llvm/ExecutionEngine/ExecutionEngine.h"
> +#include "llvm/ExecutionEngine/SectionMemoryManager.h"
> #include "llvm/Function.h"
> #include "llvm/IRBuilder.h"
> #include "llvm/LLVMContext.h"
> @@ -30,8 +31,6 @@
> #include "llvm/Support/TargetSelect.h"
> #include "llvm/TypeBuilder.h"
> 
> -#include "SectionMemoryManager.h"
> -
> // Used to skip tests on unsupported architectures and operating systems.
> // To skip a test, add this macro at the top of a test-case in a suite 
> that // inherits from MCJITTestBase. See MCJITTest.cpp for examples.
> 
> Removed: 
> llvm/trunk/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngi
> ne/MCJIT/SectionMemoryManager.cpp?rev=168720&view=auto
> ======================================================================
> ========
> --- 
> llvm/trunk/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.cpp 
> (original)
> +++ llvm/trunk/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.cp
> +++ p (removed)
> @@ -1,226 +0,0 @@
> -//===- SectionMemoryManager.cpp - Memory manager for MCJIT/RtDyld *- 
> C++ -*-==// -//
> -//                     The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open 
> Source -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------
> ------===//
> -//
> -// This file implements the section-based memory manager used by the 
> MCJIT -// execution engine and RuntimeDyld -// 
> -//===----------------------------------------------------------------
> ------===//
> -
> -#include "llvm/Config/config.h"
> -#include "llvm/Support/DynamicLibrary.h"
> -#include "llvm/Support/MathExtras.h"
> -#include "SectionMemoryManager.h"
> -
> -#ifdef __linux__
> -  // These includes used by 
> SectionMemoryManager::getPointerToNamedFunction()
> -  // for Glibc trickery. See comments in this function for more information.
> -  #ifdef HAVE_SYS_STAT_H
> -    #include <sys/stat.h>
> -  #endif
> -  #include <fcntl.h>
> -  #include <unistd.h>
> -#endif
> -
> -namespace llvm {
> -
> -uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size,
> -                                                    unsigned Alignment,
> -                                                    unsigned SectionID,
> -                                                    bool IsReadOnly) {
> -  if (IsReadOnly)
> -    return allocateSection(RODataMem, Size, Alignment);
> -  return allocateSection(RWDataMem, Size, Alignment); -}
> -
> -uint8_t *SectionMemoryManager::allocateCodeSection(uintptr_t Size,
> -                                                   unsigned Alignment,
> -                                                   unsigned SectionID) {
> -  return allocateSection(CodeMem, Size, Alignment); -}
> -
> -uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup,
> -                                               uintptr_t Size,
> -                                               unsigned Alignment) {
> -  if (!Alignment)
> -    Alignment = 16;
> -
> -  assert(!(Alignment & (Alignment - 1)) && "Alignment must be a power 
> of two.");
> -
> -  uintptr_t RequiredSize = Alignment * ((Size + Alignment - 
> 1)/Alignment + 1);
> -  uintptr_t Addr = 0;
> -
> -  // Look in the list of free memory regions and use a block there if 
> one
> -  // is available.
> -  for (int i = 0, e = MemGroup.FreeMem.size(); i != e; ++i) {
> -    sys::MemoryBlock &MB = MemGroup.FreeMem[i];
> -    if (MB.size() >= RequiredSize) {
> -      Addr = (uintptr_t)MB.base();
> -      uintptr_t EndOfBlock = Addr + MB.size();
> -      // Align the address.
> -      Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
> -      // Store cutted free memory block.
> -      MemGroup.FreeMem[i] = sys::MemoryBlock((void*)(Addr + Size),
> -                                             EndOfBlock - Addr - Size);
> -      return (uint8_t*)Addr;
> -    }
> -  }
> -
> -  // No pre-allocated free block was large enough. Allocate a new memory region.
> -  // Note that all sections get allocated as read-write.  The 
> permissions will
> -  // be updated later based on memory group.
> -  //
> -  // FIXME: It would be useful to define a default allocation size 
> (or add
> -  // it as a constructor parameter) to minimize the number of allocations.
> -  //
> -  // FIXME: Initialize the Near member for each memory group to avoid
> -  // interleaving.
> -  error_code ec;
> -  sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(RequiredSize,
> -                                                          &MemGroup.Near,
> -                                                          sys::Memory::MF_READ |
> -                                                            sys::Memory::MF_WRITE,
> -                                                          ec);
> -  if (ec) {
> -    // FIXME: Add error propogation to the interface.
> -    return NULL;
> -  }
> -
> -  // Save this address as the basis for our next request
> -  MemGroup.Near = MB;
> -
> -  MemGroup.AllocatedMem.push_back(MB);
> -  Addr = (uintptr_t)MB.base();
> -  uintptr_t EndOfBlock = Addr + MB.size();
> -
> -  // Align the address.
> -  Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
> -
> -  // The allocateMappedMemory may allocate much more memory than we 
> need. In
> -  // this case, we store the unused memory as a free memory block.
> -  unsigned FreeSize = EndOfBlock-Addr-Size;
> -  if (FreeSize > 16)
> -    MemGroup.FreeMem.push_back(sys::MemoryBlock((void*)(Addr + Size), FreeSize));
> -
> -  // Return aligned address
> -  return (uint8_t*)Addr;
> -}
> -
> -bool SectionMemoryManager::applyPermissions(std::string *ErrMsg) -{
> -  // FIXME: Should in-progress permissions be reverted if an error occurs?
> -  error_code ec;
> -
> -  // Make code memory executable.
> -  ec = applyMemoryGroupPermissions(CodeMem,
> -                                   sys::Memory::MF_READ | sys::Memory::MF_EXEC);
> -  if (ec) {
> -    if (ErrMsg) {
> -      *ErrMsg = ec.message();
> -    }
> -    return true;
> -  }
> -
> -  // Make read-only data memory read-only.
> -  ec = applyMemoryGroupPermissions(RODataMem,
> -                                   sys::Memory::MF_READ | sys::Memory::MF_EXEC);
> -  if (ec) {
> -    if (ErrMsg) {
> -      *ErrMsg = ec.message();
> -    }
> -    return true;
> -  }
> -
> -  // Read-write data memory already has the correct permissions
> -
> -  return false;
> -}
> -
> -error_code SectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup,
> -                                                             unsigned Permissions) {
> -
> -  for (int i = 0, e = MemGroup.AllocatedMem.size(); i != e; ++i) {
> -      error_code ec;
> -      ec = sys::Memory::protectMappedMemory(MemGroup.AllocatedMem[i],
> -                                            Permissions);
> -      if (ec) {
> -        return ec;
> -      }
> -  }
> -
> -  return error_code::success();
> -}
> -
> -void SectionMemoryManager::invalidateInstructionCache() {
> -  for (int i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i)
> -    sys::Memory::InvalidateInstructionCache(CodeMem.AllocatedMem[i].base(),
> -                                            CodeMem.AllocatedMem[i].size());
> -}
> -
> -static int jit_noop() {
> -  return 0;
> -}
> -
> -void *SectionMemoryManager::getPointerToNamedFunction(const std::string &Name,
> -                                                       bool AbortOnFailure) {
> -#if defined(__linux__)
> -  
> //===-----------------------------------------------------------------
> ---===//
> -  // Function stubs that are invoked instead of certain library calls
> -  //
> -  // Force the following functions to be linked in to anything that 
> uses the
> -  // JIT. This is a hack designed to work around the all-too-clever 
> Glibc
> -  // strategy of making these functions work differently when inlined 
> vs. when
> -  // not inlined, and hiding their real definitions in a separate 
> archive file
> -  // that the dynamic linker can't see. For more info, search for
> -  // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
> -  if (Name == "stat") return (void*)(intptr_t)&stat;
> -  if (Name == "fstat") return (void*)(intptr_t)&fstat;
> -  if (Name == "lstat") return (void*)(intptr_t)&lstat;
> -  if (Name == "stat64") return (void*)(intptr_t)&stat64;
> -  if (Name == "fstat64") return (void*)(intptr_t)&fstat64;
> -  if (Name == "lstat64") return (void*)(intptr_t)&lstat64;
> -  if (Name == "atexit") return (void*)(intptr_t)&atexit;
> -  if (Name == "mknod") return (void*)(intptr_t)&mknod; -#endif // 
> __linux__
> -
> -  // We should not invoke parent's ctors/dtors from generated main()!
> -  // On Mingw and Cygwin, the symbol __main is resolved to
> -  // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors
> -  // (and register wrong callee's dtors with atexit(3)).
> -  // We expect ExecutionEngine::runStaticConstructorsDestructors()
> -  // is called before ExecutionEngine::runFunctionAsMain() is called.
> -  if (Name == "__main") return (void*)(intptr_t)&jit_noop;
> -
> -  const char *NameStr = Name.c_str();
> -  void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
> -  if (Ptr) return Ptr;
> -
> -  // If it wasn't found and if it starts with an underscore ('_') 
> character,
> -  // try again without the underscore.
> -  if (NameStr[0] == '_') {
> -    Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
> -    if (Ptr) return Ptr;
> -  }
> -
> -  if (AbortOnFailure)
> -    report_fatal_error("Program used external function '" + Name +
> -                      "' which could not be resolved!");
> -  return 0;
> -}
> -
> -SectionMemoryManager::~SectionMemoryManager() {
> -  for (unsigned i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i)
> -    sys::Memory::releaseMappedMemory(CodeMem.AllocatedMem[i]);
> -  for (unsigned i = 0, e = RWDataMem.AllocatedMem.size(); i != e; ++i)
> -    sys::Memory::releaseMappedMemory(RWDataMem.AllocatedMem[i]);
> -  for (unsigned i = 0, e = RODataMem.AllocatedMem.size(); i != e; ++i)
> -    sys::Memory::releaseMappedMemory(RODataMem.AllocatedMem[i]);
> -}
> -
> -} // namespace llvm
> -
> 
> Removed: 
> llvm/trunk/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.h
> URL: 
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngi
> ne/MCJIT/SectionMemoryManager.h?rev=168720&view=auto
> ======================================================================
> ========
> --- llvm/trunk/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.h 
> (original)
> +++ llvm/trunk/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.h 
> +++ (removed)
> @@ -1,176 +0,0 @@
> -//===- SectionMemoryManager.h - Memory manager for MCJIT/RtDyld -*- 
> C++ -*-===// -//
> -//                     The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open 
> Source -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------
> ------===//
> -//
> -// This file contains the declaration of a section-based memory 
> manager used by -// the MCJIT execution engine and RuntimeDyld.
> -//
> -//===----------------------------------------------------------------
> ------===//
> -
> -#ifndef LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H
> -#define LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H
> -
> -#include "llvm/ADT/SmallVector.h"
> -#include "llvm/ExecutionEngine/JITMemoryManager.h"
> -#include "llvm/Support/ErrorHandling.h"
> -#include "llvm/Support/Memory.h"
> -
> -namespace llvm {
> -
> -/// This is a simple memory manager which implements the methods 
> called by -/// the RuntimeDyld class to allocate memory for 
> section-based loading of -/// objects, usually those generated by the MCJIT execution engine.
> -///
> -/// This memory manager allocates all section memory as read-write.  
> The -/// RuntimeDyld will copy JITed section memory into these 
> allocated blocks -/// and perform any necessary linking and relocations.
> -///
> -/// 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
> -/// directly.  Clients of MCJIT should call MCJIT::finalizeObject.
> -class SectionMemoryManager : public JITMemoryManager {
> -  SectionMemoryManager(const SectionMemoryManager&) 
> LLVM_DELETED_FUNCTION;
> -  void operator=(const SectionMemoryManager&) LLVM_DELETED_FUNCTION;
> -
> -public:
> -  SectionMemoryManager() { }
> -  virtual ~SectionMemoryManager();
> -
> -  /// \brief Allocates a memory block of (at least) the given size 
> suitable for
> -  /// executable code.
> -  ///
> -  /// The value of \p Alignment must be a power of two.  If \p 
> Alignment is zero
> -  /// a default alignment of 16 will be used.
> -  virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
> -                                       unsigned SectionID);
> -
> -  /// \brief Allocates a memory block of (at least) the given size 
> suitable for
> -  /// executable code.
> -  ///
> -  /// The value of \p Alignment must be a power of two.  If \p 
> Alignment is zero
> -  /// a default alignment of 16 will be used.
> -  virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
> -                                       unsigned SectionID,
> -                                       bool isReadOnly);
> -
> -  /// \brief Applies section-specific memory permissions.
> -  ///
> -  /// 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.
> -  ///
> -  /// \returns true if an error occurred, false otherwise.
> -  virtual bool applyPermissions(std::string *ErrMsg = 0);
> -
> -  /// This method returns the address of the specified function. As 
> such it is
> -  /// only useful for resolving library symbols, not code generated symbols.
> -  ///
> -  /// If \p AbortOnFailure is false and no function with the given 
> name is
> -  /// found, this function returns a null pointer. Otherwise, it 
> prints a
> -  /// message to stderr and aborts.
> -  virtual void *getPointerToNamedFunction(const std::string &Name,
> -                                          bool AbortOnFailure = true);
> -
> -  /// \brief Invalidate instruction cache for code sections.
> -  ///
> -  /// Some platforms with separate data cache and instruction cache 
> require
> -  /// 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 not called by RuntimeDyld or MCJIT during the 
> load
> -  /// process.  Clients may call this function when needed.  See the 
> lli
> -  /// tool for example use.
> -  virtual void invalidateInstructionCache();
> -
> -private:
> -  struct MemoryGroup {
> -      SmallVector<sys::MemoryBlock, 16> AllocatedMem;
> -      SmallVector<sys::MemoryBlock, 16> FreeMem;
> -      sys::MemoryBlock Near;
> -  };
> -
> -  uint8_t *allocateSection(MemoryGroup &MemGroup, uintptr_t Size,
> -                           unsigned Alignment);
> -
> -  error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup,
> -                                         unsigned Permissions);
> -
> -  MemoryGroup CodeMem;
> -  MemoryGroup RWDataMem;
> -  MemoryGroup RODataMem;
> -
> -public:
> -  ///
> -  /// Functions below are not used by MCJIT or RuntimeDyld, but must 
> be
> -  /// implemented because they are declared as pure virtuals in the base class.
> -  ///
> -
> -  virtual void setMemoryWritable() {
> -    llvm_unreachable("Unexpected call!");
> -  }
> -  virtual void setMemoryExecutable() {
> -    llvm_unreachable("Unexpected call!");
> -  }
> -  virtual void setPoisonMemory(bool poison) {
> -    llvm_unreachable("Unexpected call!");
> -  }
> -  virtual void AllocateGOT() {
> -    llvm_unreachable("Unexpected call!");
> -  }
> -  virtual uint8_t *getGOTBase() const {
> -    llvm_unreachable("Unexpected call!");
> -    return 0;
> -  }
> -  virtual uint8_t *startFunctionBody(const Function *F,
> -                                     uintptr_t &ActualSize){
> -    llvm_unreachable("Unexpected call!");
> -    return 0;
> -  }
> -  virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
> -                                unsigned Alignment) {
> -    llvm_unreachable("Unexpected call!");
> -    return 0;
> -  }
> -  virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart,
> -                               uint8_t *FunctionEnd) {
> -    llvm_unreachable("Unexpected call!");
> -  }
> -  virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
> -    llvm_unreachable("Unexpected call!");
> -    return 0;
> -  }
> -  virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
> -    llvm_unreachable("Unexpected call!");
> -    return 0;
> -  }
> -  virtual void deallocateFunctionBody(void *Body) {
> -    llvm_unreachable("Unexpected call!");
> -  }
> -  virtual uint8_t *startExceptionTable(const Function *F,
> -                                       uintptr_t &ActualSize) {
> -    llvm_unreachable("Unexpected call!");
> -    return 0;
> -  }
> -  virtual void endExceptionTable(const Function *F, uint8_t *TableStart,
> -                                 uint8_t *TableEnd, uint8_t *FrameRegister) {
> -    llvm_unreachable("Unexpected call!");
> -  }
> -  virtual void deallocateExceptionTable(void *ET) {
> -    llvm_unreachable("Unexpected call!");
> -  }
> -};
> -
> -}
> -
> -#endif // LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H
> -
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits





More information about the llvm-commits mailing list