From 31649e61bcead26a63c7cd452da90fff5e000b91 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Fri, 18 Mar 2011 22:48:41 +0000 Subject: [PATCH] Beginnings of MC-JIT code generation. Proof-of-concept code that code-gens a module to an in-memory MachO object. This will be hooked up to a run-time dynamic linker library (see: llvm-rtdyld for similarly conceptual work for that part) which will take the compiled object and link it together with the rest of the system, providing back to the JIT a table of available symbols which will be used to respond to the getPointerTo*() queries. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127916 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetMachine.h | 3 +++ lib/CodeGen/LLVMTargetMachine.cpp | 26 ++++++++++++++++++++++++++ lib/ExecutionEngine/MCJIT/MCJIT.cpp | 32 +++++++++++++++++++++++++++----- lib/ExecutionEngine/MCJIT/MCJIT.h | 21 ++++++++++++++++++++- tools/lli/lli.cpp | 1 + 5 files changed, 77 insertions(+), 6 deletions(-) diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 030bf5b89f7..7dd5c4ef159 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -38,6 +38,7 @@ class PassManager; class Pass; class TargetELFWriterInfo; class formatted_raw_ostream; +class raw_ostream; // Relocation model types. namespace Reloc { @@ -267,6 +268,7 @@ public: /// virtual bool addPassesToEmitMC(PassManagerBase &, MCContext *&, + raw_ostream &OS, CodeGenOpt::Level, bool = true) { return true; @@ -324,6 +326,7 @@ public: /// virtual bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx, + raw_ostream &OS, CodeGenOpt::Level OptLevel, bool DisableVerify = true); diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 377f80db7bf..a9e8045918f 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -224,11 +224,37 @@ bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, /// bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx, + raw_ostream &Out, CodeGenOpt::Level OptLevel, bool DisableVerify) { // Add common CodeGen passes. if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify, Ctx)) return true; + + // Create the code emitter for the target if it exists. If not, .o file + // emission fails. + MCCodeEmitter *MCE = getTarget().createCodeEmitter(*this, *Ctx); + TargetAsmBackend *TAB = getTarget().createAsmBackend(TargetTriple); + if (MCE == 0 || TAB == 0) + return true; + + OwningPtr AsmStreamer; + AsmStreamer.reset(getTarget().createObjectStreamer(TargetTriple, *Ctx, + *TAB, Out, MCE, + hasMCRelaxAll(), + hasMCNoExecStack())); + AsmStreamer.get()->InitSections(); + + // Create the AsmPrinter, which takes ownership of AsmStreamer if successful. + FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer); + if (Printer == 0) + return true; + + // If successful, createAsmPrinter took ownership of AsmStreamer. + AsmStreamer.take(); + + PM.add(Printer); + // Make sure the code model is set. setCodeModelForJIT(); diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index f1e9dab250b..2b5ec5de7f9 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -8,10 +8,12 @@ //===----------------------------------------------------------------------===// #include "MCJIT.h" +#include "llvm/Function.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/DynamicLibrary.h" +#include "llvm/Target/TargetData.h" using namespace llvm; @@ -51,17 +53,34 @@ 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, JMM, OptLevel, GVsWithCode); if (ErrorStr) *ErrorStr = "target does not support JIT code generation"; return 0; } -MCJIT::MCJIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, +MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji, JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool AllocateGVsWithCode) - : ExecutionEngine(M) { + : ExecutionEngine(m), TM(tm), M(m), OS(Buffer) { + + PM.add(new TargetData(*TM->getTargetData())); + + // Turn the machine code intermediate representation into bytes in memory + // that may be executed. + if (TM->addPassesToEmitMC(PM, Ctx, OS, CodeGenOpt::Default, false)) { + report_fatal_error("Target does not support MC emission!"); + } + + // Initialize passes. + ExecutionEngine::addModule(M); + // FIXME: When we support multiple modules, we'll want to move the code + // gen and finalization out of the constructor here and do it more + // on-demand as part of getPointerToFunction(). + PM.run(*M); + // Flush the output buffer so the SmallVector gets its data. + OS.flush(); } MCJIT::~MCJIT() { @@ -73,7 +92,6 @@ void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) { } void *MCJIT::getPointerToFunction(Function *F) { - report_fatal_error("not yet implemented"); return 0; } @@ -87,6 +105,10 @@ void MCJIT::freeMachineCodeForFunction(Function *F) { GenericValue MCJIT::runFunction(Function *F, const std::vector &ArgValues) { - report_fatal_error("not yet implemented"); + assert(ArgValues.size() == 0 && "JIT arg passing not supported yet"); + void *FPtr = getPointerToFunction(F); + if (!FPtr) + report_fatal_error("Unable to locate function: '" + F->getName() + "'"); + ((void(*)(void))FPtr)(); return GenericValue(); } diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h index cd1f989b10c..e81e7c7d347 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -10,14 +10,33 @@ #ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_H #define LLVM_LIB_EXECUTIONENGINE_MCJIT_H +#include "llvm/PassManager.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { +// FIXME: This makes all kinds of horrible assumptions for the time being, +// like only having one module, not needing to worry about multi-threading, +// blah blah. Purely in get-it-up-and-limping mode for now. + class MCJIT : public ExecutionEngine { - MCJIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, + MCJIT(Module *M, TargetMachine *tm, TargetJITInfo &tji, JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool AllocateGVsWithCode); + + TargetMachine *TM; + MCContext *Ctx; + + // 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. + PassManager PM; + Module *M; + // FIXME: This really doesn't belong here. + SmallVector Buffer; // Working buffer into which we JIT. + raw_svector_ostream OS; + public: ~MCJIT(); diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index a756459ecc2..014925c1a90 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -133,6 +133,7 @@ int main(int argc, char **argv, char * const *envp) { // If we have a native target, initialize it to ensure it is linked in and // usable by the JIT. InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); cl::ParseCommandLineOptions(argc, argv, "llvm interpreter & dynamic compiler\n"); -- 2.11.0