[llvm] r201259 - Extend RTDyld API to enable optionally precomputing the total amount of memory
Juergen Ributzka
juergen at apple.com
Wed Feb 12 15:13:46 PST 2014
Hi Lang,
the test case fails on my machine:
FAIL: LLVM-Unit :: ExecutionEngine/MCJIT/MCJITTests/MCJITCAPITest.reserve_allocation_space (9267 of 9728)
******************** TEST 'LLVM-Unit :: ExecutionEngine/MCJIT/MCJITTests/MCJITCAPITest.reserve_allocation_space' FAILED ********************
Note: Google Test filter = MCJITCAPITest.reserve_allocation_space
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from MCJITCAPITest
[ RUN ] MCJITCAPITest.reserve_allocation_space
llvm/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp:325: Failure
Value of: MM->UsedDataSizeRO > 0
Actual: false
Expected: true
Cheers,
Juergen
On Feb 12, 2014, at 1:30 PM, Lang Hames <lhames at gmail.com> wrote:
> Author: lhames
> Date: Wed Feb 12 15:30:07 2014
> New Revision: 201259
>
> URL: http://llvm.org/viewvc/llvm-project?rev=201259&view=rev
> Log:
> Extend RTDyld API to enable optionally precomputing the total amount of memory
> required for all sections in a module. This can be useful when targets or
> code-models place strict requirements on how sections must be laid out
> in memory.
>
> If RTDyldMemoryManger::needsToReserveAllocationSpace() is overridden to return
> true then the JIT will call the following method on the memory manager, which
> can be used to preallocate the necessary memory.
>
> void RTDyldMemoryManager::reserveAllocationSpace(uintptr_t CodeSize,
> uintptr_t DataSizeRO,
> uintptr_t DataSizeRW)
>
> Patch by Vaidas Gasiunas. Thanks very much Viadas!
>
>
> Modified:
> llvm/trunk/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
> llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.h
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
> llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
>
> Modified: llvm/trunk/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/RTDyldMemoryManager.h?rev=201259&r1=201258&r2=201259&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/ExecutionEngine/RTDyldMemoryManager.h (original)
> +++ llvm/trunk/include/llvm/ExecutionEngine/RTDyldMemoryManager.h Wed Feb 12 15:30:07 2014
> @@ -52,6 +52,20 @@ public:
> uintptr_t Size, unsigned Alignment, unsigned SectionID,
> StringRef SectionName, bool IsReadOnly) = 0;
>
> + /// Inform the memory manager about the total amount of memory required to
> + /// allocate all sections to be loaded:
> + /// \p CodeSize - the total size of all code sections
> + /// \p DataSizeRO - the total size of all read-only data sections
> + /// \p DataSizeRW - the total size of all read-write data sections
> + ///
> + /// Note that by default the callback is disabled. To enable it
> + /// redefine the method needsToReserveAllocationSpace to return true.
> + virtual void reserveAllocationSpace(
> + uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) { }
> +
> + /// Override to return true to enable the reserveAllocationSpace callback.
> + virtual bool needsToReserveAllocationSpace() { return false; }
> +
> /// Register the EH frames with the runtime so that c++ exceptions work.
> ///
> /// \p Addr parameter provides the local address of the EH frame section
>
> Modified: llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.h?rev=201259&r1=201258&r2=201259&view=diff
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.h (original)
> +++ llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.h Wed Feb 12 15:30:07 2014
> @@ -45,6 +45,15 @@ public:
> return ClientMM->allocateDataSection(Size, Alignment,
> SectionID, SectionName, IsReadOnly);
> }
> +
> + virtual void reserveAllocationSpace(
> + uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) {
> + return ClientMM->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW);
> + }
> +
> + virtual bool needsToReserveAllocationSpace() {
> + return ClientMM->needsToReserveAllocationSpace();
> + }
>
> virtual void notifyObjectLoaded(ExecutionEngine *EE,
> const ObjectImage *Obj) {
>
> Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp?rev=201259&r1=201258&r2=201259&view=diff
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp (original)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp Wed Feb 12 15:30:07 2014
> @@ -19,7 +19,6 @@
> #include "RuntimeDyldImpl.h"
> #include "RuntimeDyldMachO.h"
> #include "llvm/Object/ELF.h"
> -#include "llvm/Support/FileSystem.h"
> #include "llvm/Support/MathExtras.h"
> #include "llvm/Support/MutexGuard.h"
>
> @@ -97,14 +96,22 @@ ObjectImage *RuntimeDyldImpl::loadObject
> ObjectImage *RuntimeDyldImpl::loadObject(ObjectImage *InputObject) {
> MutexGuard locked(lock);
>
> - OwningPtr<ObjectImage> obj(InputObject);
> - if (!obj)
> + OwningPtr<ObjectImage> Obj(InputObject);
> + if (!Obj)
> return NULL;
>
> // Save information about our target
> - Arch = (Triple::ArchType)obj->getArch();
> - IsTargetLittleEndian = obj->getObjectFile()->isLittleEndian();
> -
> + Arch = (Triple::ArchType)Obj->getArch();
> + IsTargetLittleEndian = Obj->getObjectFile()->isLittleEndian();
> +
> + // Compute the memory size required to load all sections to be loaded
> + // and pass this information to the memory manager
> + if (MemMgr->needsToReserveAllocationSpace()) {
> + uint64_t CodeSize = 0, DataSizeRO = 0, DataSizeRW = 0;
> + computeTotalAllocSize(*Obj, CodeSize, DataSizeRO, DataSizeRW);
> + MemMgr->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW);
> + }
> +
> // Symbols found in this object
> StringMap<SymbolLoc> LocalSymbols;
> // Used sections from the object file
> @@ -117,24 +124,24 @@ ObjectImage *RuntimeDyldImpl::loadObject
>
> // Parse symbols
> DEBUG(dbgs() << "Parse symbols:\n");
> - for (symbol_iterator i = obj->begin_symbols(), e = obj->end_symbols(); i != e;
> - ++i) {
> + for (symbol_iterator I = Obj->begin_symbols(), E = Obj->end_symbols(); I != E;
> + ++I) {
> object::SymbolRef::Type SymType;
> StringRef Name;
> - Check(i->getType(SymType));
> - Check(i->getName(Name));
> + Check(I->getType(SymType));
> + Check(I->getName(Name));
>
> - uint32_t flags = i->getFlags();
> + uint32_t Flags = I->getFlags();
>
> - bool isCommon = flags & SymbolRef::SF_Common;
> - if (isCommon) {
> + bool IsCommon = Flags & SymbolRef::SF_Common;
> + if (IsCommon) {
> // Add the common symbols to a list. We'll allocate them all below.
> uint32_t Align;
> - Check(i->getAlignment(Align));
> + Check(I->getAlignment(Align));
> uint64_t Size = 0;
> - Check(i->getSize(Size));
> + Check(I->getSize(Size));
> CommonSize += Size + Align;
> - CommonSymbols[*i] = CommonSymbolInfo(Size, Align);
> + CommonSymbols[*I] = CommonSymbolInfo(Size, Align);
> } else {
> if (SymType == object::SymbolRef::ST_Function ||
> SymType == object::SymbolRef::ST_Data ||
> @@ -142,20 +149,20 @@ ObjectImage *RuntimeDyldImpl::loadObject
> uint64_t FileOffset;
> StringRef SectionData;
> bool IsCode;
> - section_iterator si = obj->end_sections();
> - Check(i->getFileOffset(FileOffset));
> - Check(i->getSection(si));
> - if (si == obj->end_sections()) continue;
> - Check(si->getContents(SectionData));
> - Check(si->isText(IsCode));
> + section_iterator SI = Obj->end_sections();
> + Check(I->getFileOffset(FileOffset));
> + Check(I->getSection(SI));
> + if (SI == Obj->end_sections()) continue;
> + Check(SI->getContents(SectionData));
> + Check(SI->isText(IsCode));
> const uint8_t* SymPtr = (const uint8_t*)InputObject->getData().data() +
> (uintptr_t)FileOffset;
> uintptr_t SectOffset = (uintptr_t)(SymPtr -
> (const uint8_t*)SectionData.begin());
> - unsigned SectionID = findOrEmitSection(*obj, *si, IsCode, LocalSections);
> + unsigned SectionID = findOrEmitSection(*Obj, *SI, IsCode, LocalSections);
> LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset);
> DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset)
> - << " flags: " << flags
> + << " flags: " << Flags
> << " SID: " << SectionID
> << " Offset: " << format("%p", SectOffset));
> GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset);
> @@ -166,29 +173,31 @@ ObjectImage *RuntimeDyldImpl::loadObject
>
> // Allocate common symbols
> if (CommonSize != 0)
> - emitCommonSymbols(*obj, CommonSymbols, CommonSize, LocalSymbols);
> + emitCommonSymbols(*Obj, CommonSymbols, CommonSize, LocalSymbols);
>
> // Parse and process relocations
> DEBUG(dbgs() << "Parse relocations:\n");
> - for (section_iterator si = obj->begin_sections(), se = obj->end_sections();
> - si != se; ++si) {
> - bool isFirstRelocation = true;
> + for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections();
> + SI != SE; ++SI) {
> + bool IsFirstRelocation = true;
> unsigned SectionID = 0;
> StubMap Stubs;
> - section_iterator RelocatedSection = si->getRelocatedSection();
> + section_iterator RelocatedSection = SI->getRelocatedSection();
>
> - for (relocation_iterator i = si->relocation_begin(),
> - e = si->relocation_end();
> - i != e; ++i) {
> + for (relocation_iterator I = SI->relocation_begin(),
> + E = SI->relocation_end();
> + I != E; ++I) {
> // If it's the first relocation in this section, find its SectionID
> - if (isFirstRelocation) {
> + if (IsFirstRelocation) {
> + bool IsCode = false;
> + Check(RelocatedSection->isText(IsCode));
> SectionID =
> - findOrEmitSection(*obj, *RelocatedSection, true, LocalSections);
> + findOrEmitSection(*Obj, *RelocatedSection, IsCode, LocalSections);
> DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
> - isFirstRelocation = false;
> + IsFirstRelocation = false;
> }
>
> - processRelocationRef(SectionID, *i, *obj, LocalSections, LocalSymbols,
> + processRelocationRef(SectionID, *I, *Obj, LocalSections, LocalSymbols,
> Stubs);
> }
> }
> @@ -196,7 +205,145 @@ ObjectImage *RuntimeDyldImpl::loadObject
> // Give the subclasses a chance to tie-up any loose ends.
> finalizeLoad(LocalSections);
>
> - return obj.take();
> + return Obj.take();
> +}
> +
> +// A helper method for computeTotalAllocSize.
> +// Computes the memory size required to allocate sections with the given sizes,
> +// assuming that all sections are allocated with the given alignment
> +static uint64_t computeAllocationSizeForSections(std::vector<uint64_t>& SectionSizes,
> + uint64_t Alignment) {
> + uint64_t TotalSize = 0;
> + for (size_t Idx = 0, Cnt = SectionSizes.size(); Idx < Cnt; Idx++) {
> + uint64_t AlignedSize = (SectionSizes[Idx] + Alignment - 1) /
> + Alignment * Alignment;
> + TotalSize += AlignedSize;
> + }
> + return TotalSize;
> +}
> +
> +// Compute an upper bound of the memory size that is required to load all sections
> +void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj,
> + uint64_t& CodeSize, uint64_t& DataSizeRO, uint64_t& DataSizeRW) {
> + // Compute the size of all sections required for execution
> + std::vector<uint64_t> CodeSectionSizes;
> + std::vector<uint64_t> ROSectionSizes;
> + std::vector<uint64_t> RWSectionSizes;
> + uint64_t MaxAlignment = sizeof(void*);
> +
> + // Collect sizes of all sections to be loaded;
> + // also determine the max alignment of all sections
> + for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections();
> + SI != SE; ++SI) {
> + const SectionRef &Section = *SI;
> +
> + bool IsRequired;
> + Check(Section.isRequiredForExecution(IsRequired));
> +
> + // Consider only the sections that are required to be loaded for execution
> + if (IsRequired) {
> + uint64_t DataSize = 0;
> + uint64_t Alignment64 = 0;
> + bool IsCode = false;
> + bool IsReadOnly = false;
> + StringRef Name;
> + Check(Section.getSize(DataSize));
> + Check(Section.getAlignment(Alignment64));
> + Check(Section.isText(IsCode));
> + Check(Section.isReadOnlyData(IsReadOnly));
> + Check(Section.getName(Name));
> + unsigned Alignment = (unsigned) Alignment64 & 0xffffffffL;
> +
> + uint64_t StubBufSize = computeSectionStubBufSize(Obj, Section);
> + uint64_t SectionSize = DataSize + StubBufSize;
> +
> + // The .eh_frame section (at least on Linux) needs an extra four bytes padded
> + // with zeroes added at the end. For MachO objects, this section has a
> + // slightly different name, so this won't have any effect for MachO objects.
> + if (Name == ".eh_frame")
> + SectionSize += 4;
> +
> + if (SectionSize > 0) {
> + // save the total size of the section
> + if (IsCode) {
> + CodeSectionSizes.push_back(SectionSize);
> + } else if (IsReadOnly) {
> + ROSectionSizes.push_back(SectionSize);
> + } else {
> + RWSectionSizes.push_back(SectionSize);
> + }
> + // update the max alignment
> + if (Alignment > MaxAlignment) {
> + MaxAlignment = Alignment;
> + }
> + }
> + }
> + }
> +
> + // Compute the size of all common symbols
> + uint64_t CommonSize = 0;
> + for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols();
> + I != E; ++I) {
> + uint32_t Flags = I->getFlags();
> + if (Flags & SymbolRef::SF_Common) {
> + // Add the common symbols to a list. We'll allocate them all below.
> + uint64_t Size = 0;
> + Check(I->getSize(Size));
> + CommonSize += Size;
> + }
> + }
> + if (CommonSize != 0) {
> + RWSectionSizes.push_back(CommonSize);
> + }
> +
> + // Compute the required allocation space for each different type of sections
> + // (code, read-only data, read-write data) assuming that all sections are
> + // allocated with the max alignment. Note that we cannot compute with the
> + // individual alignments of the sections, because then the required size
> + // depends on the order, in which the sections are allocated.
> + CodeSize = computeAllocationSizeForSections(CodeSectionSizes, MaxAlignment);
> + DataSizeRO = computeAllocationSizeForSections(ROSectionSizes, MaxAlignment);
> + DataSizeRW = computeAllocationSizeForSections(RWSectionSizes, MaxAlignment);
> +}
> +
> +// compute stub buffer size for the given section
> +unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj,
> + const SectionRef &Section) {
> + unsigned StubSize = getMaxStubSize();
> + if (StubSize == 0) {
> + return 0;
> + }
> + // FIXME: this is an inefficient way to handle this. We should computed the
> + // necessary section allocation size in loadObject by walking all the sections
> + // once.
> + unsigned StubBufSize = 0;
> + for (section_iterator SI = Obj.begin_sections(),
> + SE = Obj.end_sections();
> + SI != SE; ++SI) {
> + section_iterator RelSecI = SI->getRelocatedSection();
> + if (!(RelSecI == Section))
> + continue;
> +
> + for (relocation_iterator I = SI->relocation_begin(),
> + E = SI->relocation_end();
> + I != E; ++I) {
> + StubBufSize += StubSize;
> + }
> + }
> +
> + // Get section data size and alignment
> + uint64_t Alignment64;
> + uint64_t DataSize;
> + Check(Section.getSize(DataSize));
> + Check(Section.getAlignment(Alignment64));
> +
> + // Add stubbuf size alignment
> + unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
> + unsigned StubAlignment = getStubAlignment();
> + unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment);
> + if (StubAlignment > EndAlignment)
> + StubBufSize += StubAlignment - EndAlignment;
> + return StubBufSize;
> }
>
> void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj,
> @@ -244,28 +391,6 @@ unsigned RuntimeDyldImpl::emitSection(Ob
> const SectionRef &Section,
> bool IsCode) {
>
> - unsigned StubBufSize = 0,
> - StubSize = getMaxStubSize();
> - const ObjectFile *ObjFile = Obj.getObjectFile();
> - // FIXME: this is an inefficient way to handle this. We should computed the
> - // necessary section allocation size in loadObject by walking all the sections
> - // once.
> - if (StubSize > 0) {
> - for (section_iterator SI = ObjFile->section_begin(),
> - SE = ObjFile->section_end();
> - SI != SE; ++SI) {
> - section_iterator RelSecI = SI->getRelocatedSection();
> - if (!(RelSecI == Section))
> - continue;
> -
> - for (relocation_iterator I = SI->relocation_begin(),
> - E = SI->relocation_end();
> - I != E; ++I) {
> - StubBufSize += StubSize;
> - }
> - }
> - }
> -
> StringRef data;
> uint64_t Alignment64;
> Check(Section.getContents(data));
> @@ -278,6 +403,7 @@ unsigned RuntimeDyldImpl::emitSection(Ob
> bool IsReadOnly;
> uint64_t DataSize;
> unsigned PaddingSize = 0;
> + unsigned StubBufSize = 0;
> StringRef Name;
> Check(Section.isRequiredForExecution(IsRequired));
> Check(Section.isVirtual(IsVirtual));
> @@ -285,12 +411,8 @@ unsigned RuntimeDyldImpl::emitSection(Ob
> Check(Section.isReadOnlyData(IsReadOnly));
> Check(Section.getSize(DataSize));
> Check(Section.getName(Name));
> - if (StubSize > 0) {
> - unsigned StubAlignment = getStubAlignment();
> - unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment);
> - if (StubAlignment > EndAlignment)
> - StubBufSize += StubAlignment - EndAlignment;
> - }
> +
> + StubBufSize = computeSectionStubBufSize(Obj, Section);
>
> // The .eh_frame section (at least on Linux) needs an extra four bytes padded
> // with zeroes added at the end. For MachO objects, this section has a
>
> Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h?rev=201259&r1=201258&r2=201259&view=diff
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h (original)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h Wed Feb 12 15:30:07 2014
> @@ -313,6 +313,15 @@ protected:
> virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer);
> virtual ObjectImage *createObjectImageFromFile(object::ObjectFile *InputObject);
>
> + // \brief Compute an upper bound of the memory that is required to load all sections
> + void computeTotalAllocSize(ObjectImage &Obj,
> + uint64_t& CodeSize,
> + uint64_t& DataSizeRO,
> + uint64_t& DataSizeRW);
> +
> + // \brief Compute the stub buffer size required for a section
> + unsigned computeSectionStubBufSize(ObjectImage &Obj, const SectionRef &Section);
> +
> // This is the implementation for the two public overloads
> ObjectImage *loadObject(ObjectImage *InputObject);
>
>
> Modified: llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp?rev=201259&r1=201258&r2=201259&view=diff
> ==============================================================================
> --- llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp (original)
> +++ llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp Wed Feb 12 15:30:07 2014
> @@ -21,6 +21,7 @@
> #include "llvm/ExecutionEngine/SectionMemoryManager.h"
> #include "llvm/Support/Host.h"
> #include "gtest/gtest.h"
> +#include "llvm/Support/Debug.h"
>
> using namespace llvm;
>
> @@ -60,6 +61,54 @@ static void roundTripDestroy(void *objec
> }
>
> namespace {
> +
> +// memory manager to test reserve allocation space callback
> +class TestReserveAllocationSpaceMemoryManager: public SectionMemoryManager {
> +public:
> + uintptr_t ReservedCodeSize;
> + uintptr_t UsedCodeSize;
> + uintptr_t ReservedDataSizeRO;
> + uintptr_t UsedDataSizeRO;
> + uintptr_t ReservedDataSizeRW;
> + uintptr_t UsedDataSizeRW;
> +
> + TestReserveAllocationSpaceMemoryManager() :
> + ReservedCodeSize(0), UsedCodeSize(0), ReservedDataSizeRO(0),
> + UsedDataSizeRO(0), ReservedDataSizeRW(0), UsedDataSizeRW(0) {
> + }
> +
> + virtual bool needsToReserveAllocationSpace() {
> + return true;
> + }
> +
> + virtual void reserveAllocationSpace(
> + uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) {
> + ReservedCodeSize = CodeSize;
> + ReservedDataSizeRO = DataSizeRO;
> + ReservedDataSizeRW = DataSizeRW;
> + }
> +
> + void useSpace(uintptr_t* UsedSize, uintptr_t Size, unsigned Alignment) {
> + uintptr_t AlignedSize = (Size + Alignment - 1) / Alignment * Alignment;
> + uintptr_t AlignedBegin = (*UsedSize + Alignment - 1) / Alignment * Alignment;
> + *UsedSize = AlignedBegin + AlignedSize;
> + }
> +
> + virtual uint8_t* allocateDataSection(uintptr_t Size, unsigned Alignment,
> + unsigned SectionID, StringRef SectionName, bool IsReadOnly) {
> + useSpace(IsReadOnly ? &UsedDataSizeRO : &UsedDataSizeRW, Size, Alignment);
> + return SectionMemoryManager::allocateDataSection(Size, Alignment,
> + SectionID, SectionName, IsReadOnly);
> + }
> +
> + uint8_t* allocateCodeSection(uintptr_t Size, unsigned Alignment,
> + unsigned SectionID, StringRef SectionName) {
> + useSpace(&UsedCodeSize, Size, Alignment);
> + return SectionMemoryManager::allocateCodeSection(Size, Alignment,
> + SectionID, SectionName);
> + }
> +};
> +
> class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
> protected:
> MCJITCAPITest() {
> @@ -119,6 +168,54 @@ protected:
> LLVMDisposeBuilder(builder);
> }
>
> + void buildModuleWithCodeAndData() {
> + Module = LLVMModuleCreateWithName("simple_module");
> +
> + LLVMSetTarget(Module, HostTriple.c_str());
> +
> + // build a global variable initialized to "Hello World!"
> + LLVMValueRef GlobalVar = LLVMAddGlobal(Module, LLVMInt32Type(), "intVal");
> + LLVMSetInitializer(GlobalVar, LLVMConstInt(LLVMInt32Type(), 42, 0));
> +
> + {
> + Function = LLVMAddFunction(
> + Module, "getGlobal", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
> + LLVMSetFunctionCallConv(Function, LLVMCCallConv);
> +
> + LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function, "entry");
> + LLVMBuilderRef Builder = LLVMCreateBuilder();
> + LLVMPositionBuilderAtEnd(Builder, Entry);
> +
> + LLVMValueRef IntVal = LLVMBuildLoad(Builder, GlobalVar, "intVal");
> + LLVMBuildRet(Builder, IntVal);
> +
> + LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
> + LLVMDisposeMessage(Error);
> +
> + LLVMDisposeBuilder(Builder);
> + }
> +
> + {
> + LLVMTypeRef ParamTypes[] = { LLVMInt32Type() };
> + Function2 = LLVMAddFunction(
> + Module, "setGlobal", LLVMFunctionType(LLVMVoidType(), ParamTypes, 1, 0));
> + LLVMSetFunctionCallConv(Function2, LLVMCCallConv);
> +
> + LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function2, "entry");
> + LLVMBuilderRef Builder = LLVMCreateBuilder();
> + LLVMPositionBuilderAtEnd(Builder, Entry);
> +
> + LLVMValueRef Arg = LLVMGetParam(Function2, 0);
> + LLVMBuildStore(Builder, Arg, GlobalVar);
> + LLVMBuildRetVoid(Builder);
> +
> + LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
> + LLVMDisposeMessage(Error);
> +
> + LLVMDisposeBuilder(Builder);
> + }
> + }
> +
> void buildMCJITOptions() {
> LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
> Options.OptLevel = 2;
> @@ -135,7 +232,7 @@ protected:
> roundTripFinalizeMemory,
> roundTripDestroy);
> }
> -
> +
> void buildMCJITEngine() {
> ASSERT_EQ(
> 0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
> @@ -153,6 +250,7 @@ protected:
>
> LLVMModuleRef Module;
> LLVMValueRef Function;
> + LLVMValueRef Function2;
> LLVMMCJITCompilerOptions Options;
> LLVMExecutionEngineRef Engine;
> char *Error;
> @@ -194,3 +292,36 @@ TEST_F(MCJITCAPITest, custom_memory_mana
> EXPECT_EQ(42, functionPointer.usable());
> EXPECT_TRUE(didCallAllocateCodeSection);
> }
> +
> +TEST_F(MCJITCAPITest, reserve_allocation_space) {
> + SKIP_UNSUPPORTED_PLATFORM;
> +
> + TestReserveAllocationSpaceMemoryManager* MM = new TestReserveAllocationSpaceMemoryManager();
> +
> + buildModuleWithCodeAndData();
> + buildMCJITOptions();
> + Options.MCJMM = wrap(MM);
> + buildMCJITEngine();
> + buildAndRunPasses();
> +
> + union {
> + void *raw;
> + int (*usable)();
> + } GetGlobalFct;
> + GetGlobalFct.raw = LLVMGetPointerToGlobal(Engine, Function);
> +
> + union {
> + void *raw;
> + void (*usable)(int);
> + } SetGlobalFct;
> + SetGlobalFct.raw = LLVMGetPointerToGlobal(Engine, Function2);
> +
> + SetGlobalFct.usable(789);
> + EXPECT_EQ(789, GetGlobalFct.usable());
> + EXPECT_LE(MM->UsedCodeSize, MM->ReservedCodeSize);
> + EXPECT_LE(MM->UsedDataSizeRO, MM->ReservedDataSizeRO);
> + EXPECT_LE(MM->UsedDataSizeRW, MM->ReservedDataSizeRW);
> + EXPECT_TRUE(MM->UsedCodeSize > 0);
> + EXPECT_TRUE(MM->UsedDataSizeRO > 0);
> + EXPECT_TRUE(MM->UsedDataSizeRW > 0);
> +}
>
>
> _______________________________________________
> 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