diff options
| author | Chris Lattner <sabre@nondot.org> | 2003-06-01 23:24:36 +0000 | 
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2003-06-01 23:24:36 +0000 | 
| commit | 6b689e3ad44a7f14d96abf1cd003e2c224d54175 (patch) | |
| tree | 653f63890902aa4c3cc2879bbd6cc61158ad4868 /llvm/lib | |
| parent | 3bb2a00849a9416747e4e26b800b0d8f0b0f33b2 (diff) | |
| download | bcm5719-llvm-6b689e3ad44a7f14d96abf1cd003e2c224d54175.tar.gz bcm5719-llvm-6b689e3ad44a7f14d96abf1cd003e2c224d54175.zip  | |
Move target specific code to target files.  The new MachineCodeEmitter
class is actually target independent!
llvm-svn: 6517
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/ExecutionEngine/JIT/Callback.cpp | 82 | ||||
| -rw-r--r-- | llvm/lib/ExecutionEngine/JIT/Emitter.cpp | 108 | ||||
| -rw-r--r-- | llvm/lib/ExecutionEngine/JIT/JIT.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/ExecutionEngine/JIT/VM.cpp | 23 | ||||
| -rw-r--r-- | llvm/lib/ExecutionEngine/JIT/VM.h | 29 | 
5 files changed, 76 insertions, 171 deletions
diff --git a/llvm/lib/ExecutionEngine/JIT/Callback.cpp b/llvm/lib/ExecutionEngine/JIT/Callback.cpp deleted file mode 100644 index 0cb612c77f8..00000000000 --- a/llvm/lib/ExecutionEngine/JIT/Callback.cpp +++ /dev/null @@ -1,82 +0,0 @@ -//===-- Callback.cpp - Trap handler for function resolution ---------------===// -// -// This file defines the handler which is invoked when a reference to a -// non-codegen'd function is found.  This file defines target specific code -// which is used by the JIT. -// -//===----------------------------------------------------------------------===// - -#include "VM.h" -#include "Support/Statistic.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" -#include <iostream> - -static VM *TheVM = 0; - -// CompilationCallback - Invoked the first time that a call site is found, -// which causes lazy compilation of the target function. -//  -void VM::CompilationCallback() { -#if defined(i386) || defined(__i386__) || defined(__x86__) -  unsigned *StackPtr = (unsigned*)__builtin_frame_address(0); -  unsigned RetAddr = (unsigned)__builtin_return_address(0); - -  assert(StackPtr[1] == RetAddr && -         "Could not find return address on the stack!"); -  bool isStub = ((unsigned char*)RetAddr)[0] == 0xCD;  // Interrupt marker? - -  // The call instruction should have pushed the return value onto the stack... -  RetAddr -= 4;  // Backtrack to the reference itself... - -  DEBUG(std::cerr << "In callback! Addr=0x" << std::hex << RetAddr -                  << " ESP=0x" << (unsigned)StackPtr << std::dec -                  << ": Resolving call to function: " -                  << TheVM->getFunctionReferencedName((void*)RetAddr) << "\n"); - -  // Sanity check to make sure this really is a call instruction... -  assert(((unsigned char*)RetAddr)[-1] == 0xE8 && "Not a call instr!"); -   -  unsigned NewVal = (unsigned)TheVM->resolveFunctionReference((void*)RetAddr); - -  // Rewrite the call target... so that we don't fault every time we execute -  // the call. -  *(unsigned*)RetAddr = NewVal-RetAddr-4;     - -  if (isStub) { -    // If this is a stub, rewrite the call into an unconditional branch -    // instruction so that two return addresses are not pushed onto the stack -    // when the requested function finally gets called.  This also makes the -    // 0xCD byte (interrupt) dead, so the marker doesn't effect anything. -    ((unsigned char*)RetAddr)[-1] = 0xE9; -  } - -  // Change the return address to reexecute the call instruction... -  StackPtr[1] -= 5; -#else -  abort(); -#endif -} - -/// emitStubForFunction - This virtual method is used by the JIT when it needs -/// to emit the address of a function for a function whose code has not yet -/// been generated.  In order to do this, it generates a stub which jumps to -/// the lazy function compiler, which will eventually get fixed to call the -/// function directly. -/// -void *VM::emitStubForFunction(const Function &F) { -#if defined(i386) || defined(__i386__) || defined(__x86__) -  MCE->startFunctionStub(F, 6); -  MCE->emitByte(0xE8);   // Call with 32 bit pc-rel destination... -  MCE->emitGlobalAddress((GlobalValue*)&F, true); -  MCE->emitByte(0xCD);   // Interrupt - Just a marker identifying the stub! -  return MCE->finishFunctionStub(F); -#else -  abort(); -#endif -} - -void VM::registerCallback() { -  TheVM = this; -} - - diff --git a/llvm/lib/ExecutionEngine/JIT/Emitter.cpp b/llvm/lib/ExecutionEngine/JIT/Emitter.cpp index e6fe09b135e..215e9eb42b9 100644 --- a/llvm/lib/ExecutionEngine/JIT/Emitter.cpp +++ b/llvm/lib/ExecutionEngine/JIT/Emitter.cpp @@ -13,38 +13,45 @@  #include "llvm/Function.h"  #include "Support/Statistic.h" +static VM *TheVM = 0; +  namespace {    Statistic<> NumBytes("jello", "Number of bytes of machine code compiled");    class Emitter : public MachineCodeEmitter { -    VM &TheVM; - +    // CurBlock - The start of the current block of memory.  CurByte - The +    // current byte being emitted to.      unsigned char *CurBlock, *CurByte;      // When outputting a function stub in the context of some other function, we      // save CurBlock and CurByte here.      unsigned char *SavedCurBlock, *SavedCurByte; -     -    std::vector<std::pair<BasicBlock*, unsigned *> > BBRefs; -    std::map<BasicBlock*, unsigned> BBLocations; + +    // ConstantPoolAddresses - Contains the location for each entry in the +    // constant pool.      std::vector<void*> ConstantPoolAddresses;    public: -    Emitter(VM &vm) : TheVM(vm) {} +    Emitter(VM &vm) { TheVM = &vm; }      virtual void startFunction(MachineFunction &F);      virtual void finishFunction(MachineFunction &F);      virtual void emitConstantPool(MachineConstantPool *MCP); -    virtual void startBasicBlock(MachineBasicBlock &BB);      virtual void startFunctionStub(const Function &F, unsigned StubSize);      virtual void* finishFunctionStub(const Function &F);      virtual void emitByte(unsigned char B); -    virtual void emitPCRelativeDisp(Value *V); -    virtual void emitGlobalAddress(GlobalValue *V, bool isPCRelative); -    virtual void emitGlobalAddress(const std::string &Name, bool isPCRelative); -    virtual void emitFunctionConstantValueAddress(unsigned ConstantNum, -						  int Offset); -  private: -    void emitAddress(void *Addr, bool isPCRelative); +    virtual void emitWord(unsigned W); + +    virtual uint64_t getGlobalValueAddress(GlobalValue *V); +    virtual uint64_t getGlobalValueAddress(const std::string &Name); +    virtual uint64_t getConstantPoolEntryAddress(unsigned Entry); +    virtual uint64_t getCurrentPCValue(); + +    // forceCompilationOf - Force the compilation of the specified function, and +    // return its address, because we REALLY need the address now. +    // +    // FIXME: This is JIT specific! +    // +    virtual uint64_t forceCompilationOf(Function *F);    };  } @@ -66,21 +73,13 @@ static void *getMemory(unsigned NumPages) {  void Emitter::startFunction(MachineFunction &F) { -  CurBlock = (unsigned char *)getMemory(8); +  CurBlock = (unsigned char *)getMemory(16);    CurByte = CurBlock;  // Start writing at the beginning of the fn. -  TheVM.addGlobalMapping(F.getFunction(), CurBlock); +  TheVM->addGlobalMapping(F.getFunction(), CurBlock);  }  void Emitter::finishFunction(MachineFunction &F) {    ConstantPoolAddresses.clear(); -  for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) { -    unsigned Location = BBLocations[BBRefs[i].first]; -    unsigned *Ref = BBRefs[i].second; -    *Ref = Location-(unsigned)(intptr_t)Ref-4; -  } -  BBRefs.clear(); -  BBLocations.clear(); -    NumBytes += CurByte-CurBlock;    DEBUG(std::cerr << "Finished CodeGen of [0x" << std::hex @@ -95,18 +94,12 @@ void Emitter::emitConstantPool(MachineConstantPool *MCP) {      // For now we just allocate some memory on the heap, this can be      // dramatically improved.      const Type *Ty = ((Value*)Constants[i])->getType(); -    void *Addr = malloc(TheVM.getTargetData().getTypeSize(Ty)); -    TheVM.InitializeMemory(Constants[i], Addr); +    void *Addr = malloc(TheVM->getTargetData().getTypeSize(Ty)); +    TheVM->InitializeMemory(Constants[i], Addr);      ConstantPoolAddresses.push_back(Addr);    }  } - -void Emitter::startBasicBlock(MachineBasicBlock &BB) { -  BBLocations[BB.getBasicBlock()] = (unsigned)(intptr_t)CurByte; -} - -  void Emitter::startFunctionStub(const Function &F, unsigned StubSize) {    SavedCurBlock = CurBlock;  SavedCurByte = CurByte;    // FIXME: this is a huge waste of memory. @@ -129,6 +122,46 @@ void Emitter::emitByte(unsigned char B) {    *CurByte++ = B;   // Write the byte to memory  } +void Emitter::emitWord(unsigned W) { +  // FIXME: This won't work if the endianness of the host and target don't +  // agree!  (For a JIT this can't happen though.  :) +  *(unsigned*)CurByte = W; +  CurByte += sizeof(unsigned); +} + + +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); +} +uint64_t Emitter::getGlobalValueAddress(const std::string &Name) { +  return (intptr_t)TheVM->getPointerToNamedFunction(Name); +} + +// getConstantPoolEntryAddress - Return the address of the 'ConstantNum' entry +// in the constant pool that was last emitted with the 'emitConstantPool' +// method. +// +uint64_t Emitter::getConstantPoolEntryAddress(unsigned ConstantNum) { +  assert(ConstantNum < ConstantPoolAddresses.size() && +	 "Invalid ConstantPoolIndex!"); +  return (intptr_t)ConstantPoolAddresses[ConstantNum]; +} + +// getCurrentPCValue - This returns the address that the next emitted byte +// will be output to. +// +uint64_t Emitter::getCurrentPCValue() { +  return (intptr_t)CurByte; +} + +uint64_t Emitter::forceCompilationOf(Function *F) { +  return (intptr_t)TheVM->getPointerToFunction(F); +} + +#if 0 +  // emitPCRelativeDisp - For functions, just output a displacement that will  // cause a reference to the zero page, which will cause a seg-fault, causing @@ -157,23 +190,19 @@ void Emitter::emitAddress(void *Addr, bool isPCRelative) {  void Emitter::emitGlobalAddress(GlobalValue *V, bool isPCRelative) {    if (isPCRelative) { // must be a call, this is a major hack!      // Try looking up the function to see if it is already compiled! -    if (void *Addr = TheVM.getPointerToGlobalIfAvailable(V)) { +    if (void *Addr = TheVM->getPointerToGlobalIfAvailable(V)) {        emitAddress(Addr, isPCRelative);      } else {  // Function has not yet been code generated! -      TheVM.addFunctionRef(CurByte, cast<Function>(V)); +      TheVM->addFunctionRef(CurByte, cast<Function>(V));        // Delayed resolution...        emitAddress((void*)VM::CompilationCallback, isPCRelative);      }    } else { -    emitAddress(TheVM.getPointerToGlobal(V), isPCRelative); +    emitAddress(TheVM->getPointerToGlobal(V), isPCRelative);    }  } -void Emitter::emitGlobalAddress(const std::string &Name, bool isPCRelative) { -  emitAddress(TheVM.getPointerToNamedFunction(Name), isPCRelative); -} -  void Emitter::emitFunctionConstantValueAddress(unsigned ConstantNum,  					       int Offset) {    assert(ConstantNum < ConstantPoolAddresses.size() && @@ -181,3 +210,4 @@ void Emitter::emitFunctionConstantValueAddress(unsigned ConstantNum,    *(void**)CurByte = (char*)ConstantPoolAddresses[ConstantNum]+Offset;    CurByte += 4;  } +#endif diff --git a/llvm/lib/ExecutionEngine/JIT/JIT.cpp b/llvm/lib/ExecutionEngine/JIT/JIT.cpp index 95d7331f8c7..b0b6dea4727 100644 --- a/llvm/lib/ExecutionEngine/JIT/JIT.cpp +++ b/llvm/lib/ExecutionEngine/JIT/JIT.cpp @@ -43,7 +43,7 @@ ExecutionEngine *ExecutionEngine::createJIT(Module *M, unsigned Config) {    if (Arch == "x86") {      TargetMachineAllocator = allocateX86TargetMachine;    } else if (Arch == "sparc") { -    TargetMachineAllocator = allocateSparcTargetMachine; +    //TargetMachineAllocator = allocateSparcTargetMachine;    }    if (TargetMachineAllocator) { @@ -65,11 +65,10 @@ VM::VM(Module *M, TargetMachine *tm) : ExecutionEngine(M), TM(*tm) {    if (Arch == "x86") {      MCE = createX86Emitter(*this);    } else if (Arch == "sparc") { -    MCE = createSparcEmitter(*this); +    //MCE = createSparcEmitter(*this);    }    setupPassManager(); -  registerCallback();    emitGlobals();  } diff --git a/llvm/lib/ExecutionEngine/JIT/VM.cpp b/llvm/lib/ExecutionEngine/JIT/VM.cpp index c6748fa1dc7..d5815e8dd88 100644 --- a/llvm/lib/ExecutionEngine/JIT/VM.cpp +++ b/llvm/lib/ExecutionEngine/JIT/VM.cpp @@ -36,22 +36,6 @@ void VM::setupPassManager() {    }  } -void *VM::resolveFunctionReference(void *RefAddr) { -  Function *F = FunctionRefs[RefAddr]; -  assert(F && "Reference address not known!"); - -  void *Addr = getPointerToFunction(F); -  assert(Addr && "Pointer to function unknown!"); - -  FunctionRefs.erase(RefAddr); -  return Addr; -} - -const std::string &VM::getFunctionReferencedName(void *RefAddr) { -  assert(FunctionRefs[RefAddr] && "Function address unknown!"); -  return FunctionRefs[RefAddr]->getName(); -} -  /// getPointerToFunction - This method is used to get the address of the  /// specified function, compiling it if neccesary.  /// @@ -63,12 +47,7 @@ void *VM::getPointerToFunction(const Function *F) {      return Addr = getPointerToNamedFunction(F->getName());    static bool isAlreadyCodeGenerating = false; -  if (isAlreadyCodeGenerating) { -    // Generate a function stub instead of reentering... -    void *SAddr = emitStubForFunction(*F); -    assert(SAddr && "Target machine doesn't support function stub generation!"); -    return SAddr; -  } +  assert(!isAlreadyCodeGenerating && "ERROR: RECURSIVE COMPILATION DETECTED!");    // FIXME: JIT all of the functions in the module.  Eventually this will JIT    // functions on demand.  This has the effect of populating all of the diff --git a/llvm/lib/ExecutionEngine/JIT/VM.h b/llvm/lib/ExecutionEngine/JIT/VM.h index 58b7a3895b9..7c378c41c82 100644 --- a/llvm/lib/ExecutionEngine/JIT/VM.h +++ b/llvm/lib/ExecutionEngine/JIT/VM.h @@ -22,12 +22,6 @@ class VM : public ExecutionEngine {    PassManager PM;          // Passes to compile a function    MachineCodeEmitter *MCE; // MCE object -  // FunctionRefs - A mapping between addresses that refer to unresolved -  // functions and the LLVM function object itself.  This is used by the fault -  // handler to lazily patch up references... -  // -  std::map<void*, Function*> FunctionRefs; -  public:    VM(Module *M, TargetMachine *tm);    ~VM(); @@ -37,14 +31,6 @@ public:    virtual int run(const std::string &FnName,  		  const std::vector<std::string> &Args); -  void addFunctionRef(void *Ref, Function *F) { -    FunctionRefs[Ref] = F; -  } - -  const std::string &getFunctionReferencedName(void *RefAddr); - -  void *resolveFunctionReference(void *RefAddr); -    /// 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. @@ -61,21 +47,14 @@ public:    ///    static void runAtExitHandlers(); +  /// getPointerToFunction - This returns the address of the specified function, +  /// compiling it if necessary. +  void *getPointerToFunction(const Function *F); +  private:    static MachineCodeEmitter *createX86Emitter(VM &V);    static MachineCodeEmitter *createSparcEmitter(VM &V);    void setupPassManager(); -  void *getPointerToFunction(const Function *F); - -  void registerCallback(); - -  /// emitStubForFunction - This method is used by the JIT when it needs to emit -  /// the address of a function for a function whose code has not yet been -  /// generated.  In order to do this, it generates a stub which jumps to the -  /// lazy function compiler, which will eventually get fixed to call the -  /// function directly. -  /// -  void *emitStubForFunction(const Function &F);  };  #endif  | 

