[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.txt unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp unittests/ExecutionEngine/MCJIT/MCJITTestBase.h unittests/ExecutionEngine/MCJIT/SectionMemoryManager.cpp unittests/ExecutionEngine/MCJIT/SectionMemoryManager.h

Benjamin Kramer benny.kra at gmail.com
Tue Nov 27 12:17:32 PST 2012


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/ExecutionEngine/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/RuntimeDyld/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/RuntimeDyld/SectionMemoryManager.cpp?rev=168721&view=auto
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/SectionMemoryManager.cpp (added)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/SectionMemoryManager.cpp 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/ExecutionEngine/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/ExecutionEngine/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/ExecutionEngine/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/ExecutionEngine/MCJIT/SectionMemoryManager.cpp?rev=168720&view=auto
> ==============================================================================
> --- llvm/trunk/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.cpp (original)
> +++ llvm/trunk/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.cpp (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/ExecutionEngine/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