Skip to content

Commit

Permalink
Layer the memory manager between the JIT and the runtime Dyld.
Browse files Browse the repository at this point in the history
The JITMemory manager references LLVM IR constructs directly, while the
runtime Dyld works at a lower level and can handle objects which may not
originate from LLVM IR. Introduce a new layer for the memory manager to
handle the interface between them. For the MCJIT, this layer will be almost
entirely simply a call-through w/ translation between the IR objects and
symbol names.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128851 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Jim Grosbach committed Apr 4, 2011
1 parent c15a91d commit fcbe5b7
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 25 deletions.
29 changes: 26 additions & 3 deletions include/llvm/ExecutionEngine/RuntimeDyld.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,29 @@ namespace llvm {

class RuntimeDyldImpl;
class MemoryBuffer;
class JITMemoryManager;

// RuntimeDyld clients often want to handle the memory management of
// what gets placed where. For JIT clients, this is an abstraction layer
// over the JITMemoryManager, which references objects by their source
// representations in LLVM IR.
// FIXME: As the RuntimeDyld fills out, additional routines will be needed
// for the varying types of objects to be allocated.
class RTDyldMemoryManager {
RTDyldMemoryManager(const RTDyldMemoryManager&); // DO NOT IMPLEMENT
void operator=(const RTDyldMemoryManager&); // DO NOT IMPLEMENT
public:
RTDyldMemoryManager() {}

// Allocate ActualSize bytes, or more, for the named function. Return
// a pointer to the allocated memory and update Size to reflect how much
// memory was acutally allocated.
virtual uint64_t startFunctionBody(const char *Name, uintptr_t &Size) = 0;

// Mark the end of the function, including how much of the allocated
// memory was actually used.
virtual void endFunctionBody(const char *Name, uint64_t FunctionStart,
uint64_t FunctionEnd) = 0;
};

class RuntimeDyld {
RuntimeDyld(const RuntimeDyld &); // DO NOT IMPLEMENT
Expand All @@ -31,11 +53,12 @@ class RuntimeDyld {
// interface.
RuntimeDyldImpl *Dyld;
public:
RuntimeDyld(JITMemoryManager*);
RuntimeDyld(RTDyldMemoryManager*);
~RuntimeDyld();

bool loadObject(MemoryBuffer *InputBuffer);
void *getSymbolAddress(StringRef Name);
uint64_t getSymbolAddress(StringRef Name);
void reassignSymbolAddress(StringRef Name, uint64_t Addr);
// FIXME: Should be parameterized to get the memory block associated with
// a particular loaded object.
sys::MemoryBlock getMemoryBlock();
Expand Down
11 changes: 7 additions & 4 deletions lib/ExecutionEngine/MCJIT/MCJIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//

#include "MCJIT.h"
#include "MCJITMemoryManager.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/ExecutionEngine/GenericValue.h"
Expand Down Expand Up @@ -57,17 +58,18 @@ ExecutionEngine *MCJIT::createJIT(Module *M,

// If the target supports JIT code generation, create the JIT.
if (TargetJITInfo *TJ = TM->getJITInfo())
return new MCJIT(M, TM, *TJ, JMM, OptLevel, GVsWithCode);
return new MCJIT(M, TM, *TJ, new MCJITMemoryManager(JMM), OptLevel,
GVsWithCode);

if (ErrorStr)
*ErrorStr = "target does not support JIT code generation";
return 0;
}

MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji,
JITMemoryManager *JMM, CodeGenOpt::Level OptLevel,
RTDyldMemoryManager *MM, CodeGenOpt::Level OptLevel,
bool AllocateGVsWithCode)
: ExecutionEngine(m), TM(tm), M(m), OS(Buffer), Dyld(JMM) {
: ExecutionEngine(m), TM(tm), MemMgr(MM), M(m), OS(Buffer), Dyld(MM) {

PM.add(new TargetData(*TM->getTargetData()));

Expand All @@ -94,6 +96,7 @@ MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji,
}

MCJIT::~MCJIT() {
delete MemMgr;
}

void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
Expand All @@ -110,7 +113,7 @@ void *MCJIT::getPointerToFunction(Function *F) {
}

Twine Name = TM->getMCAsmInfo()->getGlobalPrefix() + F->getName();
return Dyld.getSymbolAddress(Name.str());
return (void*)Dyld.getSymbolAddress(Name.str());
}

void *MCJIT::recompileAndRelinkFunction(Function *F) {
Expand Down
3 changes: 2 additions & 1 deletion lib/ExecutionEngine/MCJIT/MCJIT.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ namespace llvm {

class MCJIT : public ExecutionEngine {
MCJIT(Module *M, TargetMachine *tm, TargetJITInfo &tji,
JITMemoryManager *JMM, CodeGenOpt::Level OptLevel,
RTDyldMemoryManager *MemMgr, CodeGenOpt::Level OptLevel,
bool AllocateGVsWithCode);

TargetMachine *TM;
MCContext *Ctx;
RTDyldMemoryManager *MemMgr;

// FIXME: These may need moved to a separate 'jitstate' member like the
// non-MC JIT does for multithreading and such. Just keep them here for now.
Expand Down
25 changes: 12 additions & 13 deletions lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/Object/MachOObject.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
Expand All @@ -35,12 +34,12 @@ class RuntimeDyldImpl {
unsigned CPUType;
unsigned CPUSubtype;

// The JITMemoryManager to load objects into.
JITMemoryManager *JMM;
// The MemoryManager to load objects into.
RTDyldMemoryManager *MemMgr;

// Master symbol table. As modules are loaded and external symbols are
// resolved, their addresses are stored here.
StringMap<void*> SymbolTable;
StringMap<uint64_t> SymbolTable;

// FIXME: Should have multiple data blocks, one for each loaded chunk of
// compiled code.
Expand Down Expand Up @@ -72,11 +71,11 @@ class RuntimeDyldImpl {
const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC);

public:
RuntimeDyldImpl(JITMemoryManager *jmm) : JMM(jmm), HasError(false) {}
RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {}

bool loadObject(MemoryBuffer *InputBuffer);

void *getSymbolAddress(StringRef Name) {
uint64_t getSymbolAddress(StringRef Name) {
// Use lookup() rather than [] because we don't want to add an entry
// if there isn't one already, which the [] operator does.
return SymbolTable.lookup(Name);
Expand Down Expand Up @@ -314,7 +313,7 @@ loadSegment32(const MachOObject *Obj,
void *SectionBase = SectionBases[Index];

// Get the symbol address.
void *Address = (char*) SectionBase + STE->Value;
uint64_t Address = (uint64_t)SectionBase + STE->Value;

// FIXME: Check the symbol type and flags.
if (STE->Type != 0xF)
Expand All @@ -335,7 +334,7 @@ loadSegment32(const MachOObject *Obj,
}

// We've loaded the section; now mark the functions in it as executable.
// FIXME: We really should use the JITMemoryManager for this.
// FIXME: We really should use the MemoryManager for this.
sys::Memory::setRangeExecutable(Data.base(), Data.size());

return false;
Expand Down Expand Up @@ -414,7 +413,7 @@ loadSegment64(const MachOObject *Obj,
void *SectionBase = SectionBases[Index];

// Get the symbol address.
void *Address = (char*) SectionBase + STE->Value;
uint64_t Address = (uint64_t) SectionBase + STE->Value;

// FIXME: Check the symbol type and flags.
if (STE->Type != 0xF)
Expand All @@ -434,7 +433,7 @@ loadSegment64(const MachOObject *Obj,
}

// We've loaded the section; now mark the functions in it as executable.
// FIXME: We really should use the JITMemoryManager for this.
// FIXME: We really should use the MemoryManager for this.
sys::Memory::setRangeExecutable(Data.base(), Data.size());

return false;
Expand Down Expand Up @@ -530,8 +529,8 @@ bool RuntimeDyldImpl::loadObject(MemoryBuffer *InputBuffer) {

//===----------------------------------------------------------------------===//
// RuntimeDyld class implementation
RuntimeDyld::RuntimeDyld(JITMemoryManager *JMM) {
Dyld = new RuntimeDyldImpl(JMM);
RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *MM) {
Dyld = new RuntimeDyldImpl(MM);
}

RuntimeDyld::~RuntimeDyld() {
Expand All @@ -542,7 +541,7 @@ bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) {
return Dyld->loadObject(InputBuffer);
}

void *RuntimeDyld::getSymbolAddress(StringRef Name) {
uint64_t RuntimeDyld::getSymbolAddress(StringRef Name) {
return Dyld->getSymbolAddress(Name);
}

Expand Down
21 changes: 17 additions & 4 deletions tools/llvm-rtdyld/llvm-rtdyld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/Object/MachOObject.h"
#include "llvm/Support/CommandLine.h"
Expand Down Expand Up @@ -41,6 +40,20 @@ Action(cl::desc("Action to perform:"),

/* *** */

// A trivial memory manager that doesn't do anything fancy, just uses the
// support library allocation routines directly.
class TrivialMemoryManager : public RTDyldMemoryManager {
public:
uint64_t startFunctionBody(const char *Name, uintptr_t &Size);
void endFunctionBody(const char *Name, uint64_t FunctionStart,
uint64_t FunctionEnd) {}
};

uint64_t TrivialMemoryManager::startFunctionBody(const char *Name,
uintptr_t &Size) {
return (uint64_t)sys::Memory::AllocateRWX(Size, 0, 0).base();
}

static const char *ProgramName;

static void Message(const char *Type, const Twine &Msg) {
Expand All @@ -61,15 +74,15 @@ static int executeInput() {
return Error("unable to read input: '" + ec.message() + "'");

// Instantiate a dynamic linker.
RuntimeDyld Dyld(JITMemoryManager::CreateDefaultMemManager());
RuntimeDyld Dyld(new TrivialMemoryManager);

// Load the object file into it.
if (Dyld.loadObject(InputBuffer.take())) {
return Error(Dyld.getErrorString());
}

// Get the address of "_main".
void *MainAddress = Dyld.getSymbolAddress("_main");
uint64_t MainAddress = Dyld.getSymbolAddress("_main");
if (MainAddress == 0)
return Error("no definition for '_main'");

Expand All @@ -83,7 +96,7 @@ static int executeInput() {
return Error("unable to mark function executable: '" + ErrorStr + "'");

// Dispatch to _main().
errs() << "loaded '_main' at: " << MainAddress << "\n";
errs() << "loaded '_main' at: " << (void*)MainAddress << "\n";

int (*Main)(int, const char**) =
(int(*)(int,const char**)) uintptr_t(MainAddress);
Expand Down

0 comments on commit fcbe5b7

Please sign in to comment.