diff options
-rw-r--r-- | lib/ExecutionEngine/JIT/Intercept.cpp | 8 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/JIT.cpp | 173 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/JIT.h | 19 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/JITEmitter.cpp | 32 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/TargetSelect.cpp | 92 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/VM.cpp | 114 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/VM.h | 94 |
7 files changed, 217 insertions, 315 deletions
diff --git a/lib/ExecutionEngine/JIT/Intercept.cpp b/lib/ExecutionEngine/JIT/Intercept.cpp index 72ac92a655..5d256f9007 100644 --- a/lib/ExecutionEngine/JIT/Intercept.cpp +++ b/lib/ExecutionEngine/JIT/Intercept.cpp @@ -15,7 +15,7 @@ // //===----------------------------------------------------------------------===// -#include "VM.h" +#include "JIT.h" #include "Support/DynamicLinker.h" #include <iostream> using namespace llvm; @@ -28,7 +28,7 @@ static std::vector<void (*)()> AtExitHandlers; /// calls to atexit(3), which we intercept and store in /// AtExitHandlers. /// -void VM::runAtExitHandlers() { +void JIT::runAtExitHandlers() { while (!AtExitHandlers.empty()) { void (*Fn)() = AtExitHandlers.back(); AtExitHandlers.pop_back(); @@ -45,7 +45,7 @@ static void NoopFn() {} // jit_exit - Used to intercept the "exit" library call. static void jit_exit(int Status) { - VM::runAtExitHandlers(); // Run atexit handlers... + JIT::runAtExitHandlers(); // Run atexit handlers... exit(Status); } @@ -61,7 +61,7 @@ static int jit_atexit(void (*Fn)(void)) { /// function by using the dynamic loader interface. As such it is only useful /// for resolving library symbols, not code generated symbols. /// -void *VM::getPointerToNamedFunction(const std::string &Name) { +void *JIT::getPointerToNamedFunction(const std::string &Name) { // Check to see if this is one of the functions we want to intercept... if (Name == "exit") return (void*)&jit_exit; if (Name == "atexit") return (void*)&jit_atexit; diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp index dc9f7a14ff..09ac4262c0 100644 --- a/lib/ExecutionEngine/JIT/JIT.cpp +++ b/lib/ExecutionEngine/JIT/JIT.cpp @@ -1,4 +1,4 @@ -//===-- JIT.cpp - LLVM Just-In-Time Compiler ------------------------------===// +//===-- JIT.cpp - LLVM Just in Time Compiler ------------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,102 +7,50 @@ // //===----------------------------------------------------------------------===// // -// This file implements the top-level support for creating a Just-In-Time -// compiler for the current architecture. +// This tool implements a just-in-time compiler for LLVM, allowing direct +// execution of LLVM bytecode in an efficient manner. // //===----------------------------------------------------------------------===// -#include "VM.h" -#include "llvm/Module.h" +#include "JIT.h" +#include "llvm/Function.h" #include "llvm/ModuleProvider.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetMachineImpls.h" -#include "Support/CommandLine.h" +#include "llvm/Target/TargetJITInfo.h" using namespace llvm; -#if !defined(ENABLE_X86_JIT) && !defined(ENABLE_SPARC_JIT) -#define NO_JITS_ENABLED -#endif - -namespace { - enum ArchName { x86, Sparc }; - -#ifndef NO_JITS_ENABLED - cl::opt<ArchName> - Arch("march", cl::desc("Architecture to JIT to:"), cl::Prefix, - cl::values( -#ifdef ENABLE_X86_JIT - clEnumVal(x86, " IA-32 (Pentium and above)"), -#endif -#ifdef ENABLE_SPARC_JIT - clEnumValN(Sparc, "sparc", " Sparc-V9"), -#endif - 0), -#if defined(ENABLE_X86_JIT) - cl::init(x86) -#elif defined(ENABLE_SPARC_JIT) - cl::init(Sparc) -#endif - ); -#endif /* NO_JITS_ENABLED */ -} - -/// create - Create an return a new JIT compiler if there is one available -/// for the current target. Otherwise, return null. -/// -ExecutionEngine *VM::create(ModuleProvider *MP) { - TargetMachine* (*TargetMachineAllocator)(const Module &) = 0; - - // Allow a command-line switch to override what *should* be the default target - // machine for this platform. This allows for debugging a Sparc JIT on X86 -- - // our X86 machines are much faster at recompiling LLVM and linking LLI. -#ifndef NO_JITS_ENABLED - - switch (Arch) { -#ifdef ENABLE_X86_JIT - case x86: - TargetMachineAllocator = allocateX86TargetMachine; - break; -#endif -#ifdef ENABLE_SPARC_JIT - case Sparc: - TargetMachineAllocator = allocateSparcTargetMachine; - break; -#endif - default: - assert(0 && "-march flag not supported on this host!"); - } -#else - return 0; -#endif - - // Allocate a target... - TargetMachine *Target = TargetMachineAllocator(*MP->getModule()); - assert(Target && "Could not allocate target machine!"); - - // If the target supports JIT code generation, return a new JIT now. - if (TargetJITInfo *TJ = Target->getJITInfo()) - return new VM(MP, *Target, *TJ); - return 0; -} - -VM::VM(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji) +JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji) : ExecutionEngine(MP), TM(tm), TJI(tji), PM(MP) { setTargetData(TM.getTargetData()); // Initialize MCE MCE = createEmitter(*this); - setupPassManager(); + // Compile LLVM Code down to machine code in the intermediate representation + TJI.addPassesToJITCompile(PM); + + // Turn the machine code intermediate representation into bytes in memory that + // may be executed. + if (TM.addPassesToEmitMachineCode(PM, *MCE)) { + std::cerr << "lli: target '" << TM.getName() + << "' doesn't support machine code emission!\n"; + abort(); + } emitGlobals(); } +JIT::~JIT() { + delete MCE; + delete &TM; +} + /// run - Start execution with the specified function and arguments. /// -GenericValue VM::run(Function *F, const std::vector<GenericValue> &ArgValues) -{ +GenericValue JIT::run(Function *F, const std::vector<GenericValue> &ArgValues) { assert (F && "Function *F was null at entry to run()"); int (*PF)(int, char **, const char **) = @@ -120,3 +68,74 @@ GenericValue VM::run(Function *F, const std::vector<GenericValue> &ArgValues) rv.IntVal = ExitCode; return rv; } + +/// runJITOnFunction - Run the FunctionPassManager full of +/// just-in-time compilation passes on F, hopefully filling in +/// GlobalAddress[F] with the address of F's machine code. +/// +void JIT::runJITOnFunction(Function *F) { + static bool isAlreadyCodeGenerating = false; + assert(!isAlreadyCodeGenerating && "Error: Recursive compilation detected!"); + + // JIT the function + isAlreadyCodeGenerating = true; + PM.run(*F); + isAlreadyCodeGenerating = false; +} + +/// getPointerToFunction - This method is used to get the address of the +/// specified function, compiling it if neccesary. +/// +void *JIT::getPointerToFunction(Function *F) { + void *&Addr = GlobalAddress[F]; // Check if function already code gen'd + if (Addr) return Addr; + + // Make sure we read in the function if it exists in this Module + MP->materializeFunction(F); + + if (F->isExternal()) + return Addr = getPointerToNamedFunction(F->getName()); + + runJITOnFunction(F); + assert(Addr && "Code generation didn't add function to GlobalAddress table!"); + return Addr; +} + +// getPointerToFunctionOrStub - If the specified function has been +// code-gen'd, return a pointer to the function. If not, compile it, or use +// a stub to implement lazy compilation if available. +// +void *JIT::getPointerToFunctionOrStub(Function *F) { + // If we have already code generated the function, just return the address. + std::map<const GlobalValue*, void *>::iterator I = GlobalAddress.find(F); + if (I != GlobalAddress.end()) return I->second; + + // If the target supports "stubs" for functions, get a stub now. + if (void *Ptr = TJI.getJITStubForFunction(F, *MCE)) + return Ptr; + + // Otherwise, if the target doesn't support it, just codegen the function. + return getPointerToFunction(F); +} + +/// recompileAndRelinkFunction - This method is used to force a function +/// which has already been compiled, to be compiled again, possibly +/// after it has been modified. Then the entry to the old copy is overwritten +/// with a branch to the new copy. If there was no old copy, this acts +/// just like JIT::getPointerToFunction(). +/// +void *JIT::recompileAndRelinkFunction(Function *F) { + void *&Addr = GlobalAddress[F]; // Check if function already code gen'd + + // If it's not already compiled (this is kind of weird) there is no + // reason to patch it up. + if (!Addr) { return getPointerToFunction (F); } + + void *OldAddr = Addr; + Addr = 0; + MachineFunction::destruct(F); + runJITOnFunction(F); + assert(Addr && "Code generation didn't add function to GlobalAddress table!"); + TJI.replaceMachineCodeForFunction(OldAddr, Addr); + return Addr; +} diff --git a/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h index 35f7223ae8..adf4e46e77 100644 --- a/lib/ExecutionEngine/JIT/JIT.h +++ b/lib/ExecutionEngine/JIT/JIT.h @@ -1,4 +1,4 @@ -//===-- VM.h - Definitions for Virtual Machine ------------------*- C++ -*-===// +//===-- JIT.h - Class definition for the JIT --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// // -// This file defines the top-level Virtual Machine data structure. +// This file defines the top-level JIT data structure. // //===----------------------------------------------------------------------===// -#ifndef VM_H -#define VM_H +#ifndef JIT_H +#define JIT_H #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/PassManager.h" @@ -27,16 +27,16 @@ class TargetMachine; class TargetJITInfo; class MachineCodeEmitter; -class VM : public ExecutionEngine { +class JIT : public ExecutionEngine { TargetMachine &TM; // The current target we are compiling to TargetJITInfo &TJI; // The JITInfo for the target we are compiling to FunctionPassManager PM; // Passes to compile a function MachineCodeEmitter *MCE; // MCE object - VM(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji); + JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji); public: - ~VM(); + ~JIT(); /// create - Create an return a new JIT compiler if there is one available /// for the current target. Otherwise, return null. @@ -79,13 +79,12 @@ public: /// which has already been compiled, to be compiled again, possibly /// after it has been modified. Then the entry to the old copy is overwritten /// with a branch to the new copy. If there was no old copy, this acts - /// just like VM::getPointerToFunction(). + /// just like JIT::getPointerToFunction(). /// void *recompileAndRelinkFunction(Function *F); private: - static MachineCodeEmitter *createEmitter(VM &V); - void setupPassManager(); + static MachineCodeEmitter *createEmitter(JIT &J); void runJITOnFunction (Function *F); }; diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index 2495360aea..50b3610e51 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -16,7 +16,7 @@ #ifndef _POSIX_MAPPED_FILES #define _POSIX_MAPPED_FILES #endif -#include "VM.h" +#include "JIT.h" #include "llvm/Constant.h" #include "llvm/Module.h" #include "llvm/CodeGen/MachineCodeEmitter.h" @@ -31,7 +31,7 @@ using namespace llvm; namespace { Statistic<> NumBytes("jit", "Number of bytes of machine code compiled"); - VM *TheVM = 0; + JIT *TheJIT = 0; /// JITMemoryManager - Manage memory for the JIT code generation in a logical, /// sane way. This splits a large block of MAP_NORESERVE'd memory into two @@ -142,7 +142,7 @@ namespace { // constant pool. std::vector<void*> ConstantPoolAddresses; public: - Emitter(VM &vm) { TheVM = &vm; } + Emitter(JIT &jit) { TheJIT = &jit; } virtual void startFunction(MachineFunction &F); virtual void finishFunction(MachineFunction &F); @@ -166,13 +166,13 @@ namespace { }; } -MachineCodeEmitter *VM::createEmitter(VM &V) { - return new Emitter(V); +MachineCodeEmitter *JIT::createEmitter(JIT &jit) { + return new Emitter(jit); } void Emitter::startFunction(MachineFunction &F) { CurByte = CurBlock = MemMgr.startFunctionBody(); - TheVM->addGlobalMapping(F.getFunction(), CurBlock); + TheJIT->addGlobalMapping(F.getFunction(), CurBlock); } void Emitter::finishFunction(MachineFunction &F) { @@ -197,8 +197,8 @@ void Emitter::emitConstantPool(MachineConstantPool *MCP) { unsigned TotalSize = 0; for (unsigned i = 0, e = Constants.size(); i != e; ++i) { const Type *Ty = Constants[i]->getType(); - unsigned Size = TheVM->getTargetData().getTypeSize(Ty); - unsigned Alignment = TheVM->getTargetData().getTypeAlignment(Ty); + unsigned Size = TheJIT->getTargetData().getTypeSize(Ty); + unsigned Alignment = TheJIT->getTargetData().getTypeAlignment(Ty); // Make sure to take into account the alignment requirements of the type. TotalSize = (TotalSize + Alignment-1) & ~(Alignment-1); @@ -213,7 +213,7 @@ void Emitter::emitConstantPool(MachineConstantPool *MCP) { // Actually output all of the constants, and remember their addresses. for (unsigned i = 0, e = Constants.size(); i != e; ++i) { void *Addr = Pool + ConstantOffset[i]; - TheVM->InitializeMemory(Constants[i], Addr); + TheJIT->InitializeMemory(Constants[i], Addr); ConstantPoolAddresses.push_back(Addr); } } @@ -248,10 +248,10 @@ void Emitter::emitWord(unsigned W) { uint64_t Emitter::getGlobalValueAddress(GlobalValue *V) { // Try looking up the function to see if it is already compiled, if not return // 0. - return (intptr_t)TheVM->getPointerToGlobalIfAvailable(V); + return (intptr_t)TheJIT->getPointerToGlobalIfAvailable(V); } uint64_t Emitter::getGlobalValueAddress(const std::string &Name) { - return (intptr_t)TheVM->getPointerToNamedFunction(Name); + return (intptr_t)TheJIT->getPointerToNamedFunction(Name); } // getConstantPoolEntryAddress - Return the address of the 'ConstantNum' entry @@ -272,19 +272,19 @@ uint64_t Emitter::getCurrentPCValue() { } uint64_t Emitter::forceCompilationOf(Function *F) { - return (intptr_t)TheVM->getPointerToFunction(F); + return (intptr_t)TheJIT->getPointerToFunction(F); } // getPointerToNamedFunction - This function is used as a global wrapper to -// VM::getPointerToNamedFunction for the purpose of resolving symbols when +// JIT::getPointerToNamedFunction for the purpose of resolving symbols when // bugpoint is debugging the JIT. In that scenario, we are loading an .so and // need to resolve function(s) that are being mis-codegenerated, so we need to // resolve their addresses at runtime, and this is the way to do it. extern "C" { void *getPointerToNamedFunction(const char *Name) { - Module &M = TheVM->getModule(); + Module &M = TheJIT->getModule(); if (Function *F = M.getNamedFunction(Name)) - return TheVM->getPointerToFunction(F); - return TheVM->getPointerToNamedFunction(Name); + return TheJIT->getPointerToFunction(F); + return TheJIT->getPointerToNamedFunction(Name); } } diff --git a/lib/ExecutionEngine/JIT/TargetSelect.cpp b/lib/ExecutionEngine/JIT/TargetSelect.cpp new file mode 100644 index 0000000000..4a381fb5a2 --- /dev/null +++ b/lib/ExecutionEngine/JIT/TargetSelect.cpp @@ -0,0 +1,92 @@ +//===-- TargetSelect.cpp - Target Chooser Code ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the hideously gross code that is currently used to select +// a particular TargetMachine for the JIT to use. This should obviously be +// improved in the future, probably by having the TargetMachines register +// themselves with the runtime, and then have them choose themselves if they +// match the current machine. +// +//===----------------------------------------------------------------------===// + +#include "JIT.h" +#include "llvm/Module.h" +#include "llvm/ModuleProvider.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetMachineImpls.h" +#include "Support/CommandLine.h" +using namespace llvm; + +#if !defined(ENABLE_X86_JIT) && !defined(ENABLE_SPARC_JIT) +#define NO_JITS_ENABLED +#endif + +namespace { + enum ArchName { x86, Sparc }; + +#ifndef NO_JITS_ENABLED + cl::opt<ArchName> + Arch("march", cl::desc("Architecture to JIT to:"), cl::Prefix, + cl::values( +#ifdef ENABLE_X86_JIT + clEnumVal(x86, " IA-32 (Pentium and above)"), +#endif +#ifdef ENABLE_SPARC_JIT + clEnumValN(Sparc, "sparc", " Sparc-V9"), +#endif + 0), +#if defined(ENABLE_X86_JIT) + cl::init(x86) +#elif defined(ENABLE_SPARC_JIT) + cl::init(Sparc) +#endif + ); +#endif /* NO_JITS_ENABLED */ +} + +/// create - Create an return a new JIT compiler if there is one available +/// for the current target. Otherwise, return null. +/// +ExecutionEngine *JIT::create(ModuleProvider *MP) { + TargetMachine* (*TargetMachineAllocator)(const Module &) = 0; + + // Allow a command-line switch to override what *should* be the default target + // machine for this platform. This allows for debugging a Sparc JIT on X86 -- + // our X86 machines are much faster at recompiling LLVM and linking LLI. +#ifndef NO_JITS_ENABLED + + switch (Arch) { +#ifdef ENABLE_X86_JIT + case x86: + TargetMachineAllocator = allocateX86TargetMachine; + break; +#endif +#ifdef ENABLE_SPARC_JIT + case Sparc: + TargetMachineAllocator = allocateSparcTargetMachine; + break; +#endif + default: + assert(0 && "-march flag not supported on this host!"); + } +#else + return 0; +#endif + + // Allocate a target... + TargetMachine *Target = TargetMachineAllocator(*MP->getModule()); + assert(Target && "Could not allocate target machine!"); + + // If the target supports JIT code generation, return a new JIT now. + if (TargetJITInfo *TJ = Target->getJITInfo()) + return new JIT(MP, *Target, *TJ); + return 0; +} + + diff --git a/lib/ExecutionEngine/JIT/VM.cpp b/lib/ExecutionEngine/JIT/VM.cpp deleted file mode 100644 index 5dffa5c913..0000000000 --- a/lib/ExecutionEngine/JIT/VM.cpp +++ /dev/null @@ -1,114 +0,0 @@ -//===-- VM.cpp - LLVM Just in Time Compiler -------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This tool implements a just-in-time compiler for LLVM, allowing direct -// execution of LLVM bytecode in an efficient manner. -// -//===----------------------------------------------------------------------===// - -#include "VM.h" -#include "llvm/Function.h" -#include "llvm/ModuleProvider.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetJITInfo.h" -using namespace llvm; - -VM::~VM() { - delete MCE; - delete &TM; -} - -/// setupPassManager - Initialize the VM PassManager object with all of the -/// passes needed for the target to generate code. -/// -void VM::setupPassManager() { - // Compile LLVM Code down to machine code in the intermediate representation - TJI.addPassesToJITCompile(PM); - - // Turn the machine code intermediate representation into bytes in memory that - // may be executed. - if (TM.addPassesToEmitMachineCode(PM, *MCE)) { - std::cerr << "lli: target '" << TM.getName() - << "' doesn't support machine code emission!\n"; - abort(); - } -} - -/// runJITOnFunction - Run the FunctionPassManager full of -/// just-in-time compilation passes on F, hopefully filling in -/// GlobalAddress[F] with the address of F's machine code. -/// -void VM::runJITOnFunction(Function *F) { - static bool isAlreadyCodeGenerating = false; - assert(!isAlreadyCodeGenerating && "Error: Recursive compilation detected!"); - - // JIT the function - isAlreadyCodeGenerating = true; - PM.run(*F); - isAlreadyCodeGenerating = false; -} - -/// getPointerToFunction - This method is used to get the address of the -/// specified function, compiling it if neccesary. -/// -void *VM::getPointerToFunction(Function *F) { - void *&Addr = GlobalAddress[F]; // Check if function already code gen'd - if (Addr) return Addr; - - // Make sure we read in the function if it exists in this Module - MP->materializeFunction(F); - - if (F->isExternal()) - return Addr = getPointerToNamedFunction(F->getName()); - - runJITOnFunction(F); - assert(Addr && "Code generation didn't add function to GlobalAddress table!"); - return Addr; -} - -// getPointerToFunctionOrStub - If the specified function has been -// code-gen'd, return a pointer to the function. If not, compile it, or use -// a stub to implement lazy compilation if available. -// -void *VM::getPointerToFunctionOrStub(Function *F) { - // If we have already code generated the function, just return the address. - std::map<const GlobalValue*, void *>::iterator I = GlobalAddress.find(F); - if (I != GlobalAddress.end()) return I->second; - - // If the target supports "stubs" for functions, get a stub now. - if (void *Ptr = TJI.getJITStubForFunction(F, *MCE)) - return Ptr; - - // Otherwise, if the target doesn't support it, just codegen the function. - return getPointerToFunction(F); -} - -/// recompileAndRelinkFunction - This method is used to force a function -/// which has already been compiled, to be compiled again, possibly -/// after it has been modified. Then the entry to the old copy is overwritten -/// with a branch to the new copy. If there was no old copy, this acts -/// just like VM::getPointerToFunction(). -/// -void *VM::recompileAndRelinkFunction(Function *F) { - void *&Addr = GlobalAddress[F]; // Check if function already code gen'd - - // If it's not already compiled (this is kind of weird) there is no - // reason to patch it up. - if (!Addr) { return getPointerToFunction (F); } - - void *OldAddr = Addr; - Addr = 0; - MachineFunction::destruct(F); - runJITOnFunction(F); - assert(Addr && "Code generation didn't add function to GlobalAddress table!"); - TJI.replaceMachineCodeForFunction(OldAddr, Addr); - return Addr; -} diff --git a/lib/ExecutionEngine/JIT/VM.h b/lib/ExecutionEngine/JIT/VM.h deleted file mode 100644 index 35f7223ae8..0000000000 --- a/lib/ExecutionEngine/JIT/VM.h +++ /dev/null @@ -1,94 +0,0 @@ -//===-- VM.h - Definitions for Virtual Machine ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the top-level Virtual Machine data structure. -// -//===----------------------------------------------------------------------===// - -#ifndef VM_H -#define VM_H - -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/PassManager.h" -#include <map> - -namespace llvm { - -class Function; -class GlobalValue; -class Constant; -class TargetMachine; -class TargetJITInfo; -class MachineCodeEmitter; - -class VM : public ExecutionEngine { - TargetMachine &TM; // The current target we are compiling to - TargetJITInfo &TJI; // The JITInfo for the target we are compiling to - - FunctionPassManager PM; // Passes to compile a function - MachineCodeEmitter *MCE; // MCE object - - VM(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji); -public: - ~VM(); - - /// create - Create an return a new JIT compiler if there is one available - /// for the current target. Otherwise, return null. - /// - static ExecutionEngine *create(ModuleProvider *MP); - - /// run - Start execution with the specified function and arguments. - /// - virtual GenericValue run(Function *F, - const std::vector<GenericValue> &ArgValues); - - /// getPointerToNamedFunction - This method returns the address of the - /// specified function by using the dlsym function call. As such it is only - /// useful for resolving library symbols, not code generated symbols. - /// - void *getPointerToNamedFunction(const std::string &Name); - - // CompilationCallback - Invoked the first time that a call site is found, - // which causes lazy compilation of the target function. - // - static void CompilationCallback(); - - /// runAtExitHandlers - Before exiting the program, at_exit functions must be - /// called. This method calls them. - /// - static void runAtExitHandlers(); - - /// getPointerToFunction - This returns the address of the specified function, - /// compiling it if necessary. - /// - void *getPointerToFunction(Function *F); - - /// getPointerToFunctionOrStub - If the specified function has been - /// code-gen'd, return a pointer to the function. If not, compile it, or use - /// a stub to implement lazy compilation if available. - /// - void *getPointerToFunctionOrStub(Function *F); - - /// recompileAndRelinkFunction - This method is used to force a function - /// which has already been compiled, to be compiled again, possibly - /// after it has been modified. Then the entry to the old copy is overwritten - /// with a branch to the new copy. If there was no old copy, this acts - /// just like VM::getPointerToFunction(). - /// - void *recompileAndRelinkFunction(Function *F); - -private: - static MachineCodeEmitter *createEmitter(VM &V); - void setupPassManager(); - void runJITOnFunction (Function *F); -}; - -} // End llvm namespace - -#endif |