diff options
author | Andrew Kaylor <andrew.kaylor@intel.com> | 2012-11-27 19:42:02 +0000 |
---|---|---|
committer | Andrew Kaylor <andrew.kaylor@intel.com> | 2012-11-27 19:42:02 +0000 |
commit | 927ba6a0b36b8219955a657545fcb1c863734993 (patch) | |
tree | 25b8bf6ceac6ae3009e7e9105b1f8f31474715a4 /unittests/ExecutionEngine/MCJIT | |
parent | 3c1cc3888bbfbb568dad296f577c63eba8999a72 (diff) | |
download | external_llvm-927ba6a0b36b8219955a657545fcb1c863734993.zip external_llvm-927ba6a0b36b8219955a657545fcb1c863734993.tar.gz external_llvm-927ba6a0b36b8219955a657545fcb1c863734993.tar.bz2 |
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168721 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/ExecutionEngine/MCJIT')
5 files changed, 175 insertions, 406 deletions
diff --git a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt index 3e9c5b6..c6b1f77 100644 --- a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt +++ b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt @@ -2,14 +2,14 @@ set(LLVM_LINK_COMPONENTS asmparser bitreader bitwriter - mcjit jit + mcjit nativecodegen ) set(MCJITTestsSources MCJITTest.cpp - SectionMemoryManager.cpp + MCJITMemoryManagerTest.cpp ) if(MSVC) diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp new file mode 100644 index 0000000..eeea9d7 --- /dev/null +++ b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp @@ -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
+
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h index 9b4a4ac..e34074b 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h @@ -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. diff --git a/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.cpp b/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.cpp deleted file mode 100644 index e8aaa82..0000000 --- a/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.cpp +++ /dev/null @@ -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 - diff --git a/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.h b/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.h deleted file mode 100644 index 7d5a5ff..0000000 --- a/unittests/ExecutionEngine/MCJIT/SectionMemoryManager.h +++ /dev/null @@ -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 - |