//===-- CodeEmitter.h - CodeEmitter Class -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See external/llvm/LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the CodeEmitter class. // //===----------------------------------------------------------------------===// #ifndef BCC_CODEEMITTER_H #define BCC_CODEEMITTER_H #include <bcc/bcc.h> #include <bcc/bcc_assert.h> #include <bcc/bcc_cache.h> #include "ExecutionEngine/bcc_internal.h" #include "Config.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineRelocation.h" #include "llvm/CodeGen/JITCodeEmitter.h" #include "llvm/Support/ValueHandle.h" #include <map> #include <vector> #include <set> #include <stdint.h> namespace llvm { class Constant; class GenericValue; class GlobalVariable; class GlobalValue; class Function; class MachineBasicBlock; class MachineFunction; class MachineJumpTableInfo; class MachineModuleInfo; class MCSymbol; class Target; class TargetData; class TargetJITInfo; class TargetMachine; class Type; } namespace bcc { class CodeMemoryManager; class ScriptCompiled; class CodeEmitter : public llvm::JITCodeEmitter { private: typedef llvm::DenseMap<const llvm::GlobalValue *, void *> GlobalAddressMapTy; typedef llvm::DenseMap<const llvm::Function *, void*> FunctionToLazyStubMapTy; typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void *> GlobalToIndirectSymMapTy; public: typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator; private: ScriptCompiled *mpResult; CodeMemoryManager *mpMemMgr; llvm::TargetMachine *mpTargetMachine; // The JITInfo for the target we are compiling to const llvm::Target *mpTarget; llvm::TargetJITInfo *mpTJI; const llvm::TargetData *mpTD; FuncInfo *mpCurEmitFunction; GlobalAddressMapTy mGlobalAddressMap; // This vector is a mapping from MBB ID's to their address. It is filled in // by the StartMachineBasicBlock callback and queried by the // getMachineBasicBlockAddress callback. std::vector<uintptr_t> mMBBLocations; // The constant pool for the current function. llvm::MachineConstantPool *mpConstantPool; // A pointer to the first entry in the constant pool. void *mpConstantPoolBase; // Addresses of individual constant pool entries. llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses; // The jump tables for the current function. llvm::MachineJumpTableInfo *mpJumpTable; // A pointer to the first entry in the jump table. void *mpJumpTableBase; // When outputting a function stub in the context of some other function, we // save BufferBegin/BufferEnd/CurBufferPtr here. uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr; // These are the relocations that the function needs, as emitted. std::vector<llvm::MachineRelocation> mRelocations; #if 0 std::vector<oBCCRelocEntry> mCachingRelocations; #endif // This vector is a mapping from Label ID's to their address. llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations; // Machine module info for exception informations llvm::MachineModuleInfo *mpMMI; FunctionToLazyStubMapTy mFunctionToLazyStubMap; std::set<const llvm::Function*> PendingFunctions; GlobalToIndirectSymMapTy GlobalToIndirectSymMap; std::map<void*, void*> ExternalFnToStubMap; public: // Resolver to undefined symbol in CodeEmitter BCCSymbolLookupFn mpSymbolLookupFn; void *mpSymbolLookupContext; // Will take the ownership of @MemMgr explicit CodeEmitter(ScriptCompiled *result, CodeMemoryManager *pMemMgr); virtual ~CodeEmitter(); global_addresses_const_iterator global_address_begin() const { return mGlobalAddressMap.begin(); } global_addresses_const_iterator global_address_end() const { return mGlobalAddressMap.end(); } #if 0 std::vector<oBCCRelocEntry> const &getCachingRelocations() const { return mCachingRelocations; } #endif void registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) { mpSymbolLookupFn = pFn; mpSymbolLookupContext = pContext; } void setTargetMachine(llvm::TargetMachine &TM); // This callback is invoked when the specified function is about to be code // generated. This initializes the BufferBegin/End/Ptr fields. virtual void startFunction(llvm::MachineFunction &F); // This callback is invoked when the specified function has finished code // generation. If a buffer overflow has occurred, this method returns true // (the callee is required to try again). virtual bool finishFunction(llvm::MachineFunction &F); // Allocates and fills storage for an indirect GlobalValue, and returns the // address. virtual void *allocIndirectGV(const llvm::GlobalValue *GV, const uint8_t *Buffer, size_t Size, unsigned Alignment); // Emits a label virtual void emitLabel(llvm::MCSymbol *Label) { mLabelLocations[Label] = getCurrentPCValue(); } // Allocate memory for a global. Unlike allocateSpace, this method does not // allocate memory in the current output buffer, because a global may live // longer than the current function. virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment); // This should be called by the target when a new basic block is about to be // emitted. This way the MCE knows where the start of the block is, and can // implement getMachineBasicBlockAddress. virtual void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB); // Whenever a relocatable address is needed, it should be noted with this // interface. virtual void addRelocation(const llvm::MachineRelocation &MR) { mRelocations.push_back(MR); } // Return the address of the @Index entry in the constant pool that was // last emitted with the emitConstantPool method. virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const { bccAssert(Index < mpConstantPool->getConstants().size() && "Invalid constant pool index!"); return mConstPoolAddresses[Index]; } // Return the address of the jump table with index @Index in the function // that last called initJumpTableInfo. virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const; // Return the address of the specified MachineBasicBlock, only usable after // the label for the MBB has been emitted. virtual uintptr_t getMachineBasicBlockAddress( llvm::MachineBasicBlock *MBB) const; // Return the address of the specified LabelID, only usable after the // LabelID has been emitted. virtual uintptr_t getLabelAddress(llvm::MCSymbol *Label) const { bccAssert(mLabelLocations.count(Label) && "Label not emitted!"); return mLabelLocations.find(Label)->second; } // Specifies the MachineModuleInfo object. This is used for exception // handling purposes. virtual void setModuleInfo(llvm::MachineModuleInfo *Info) { mpMMI = Info; } void releaseUnnecessary(); void reset(); private: void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize, unsigned Alignment); void startGVStub(void *Buffer, unsigned StubSize); void finishGVStub(); // Replace an existing mapping for GV with a new address. This updates both // maps as required. If Addr is null, the entry for the global is removed // from the mappings. void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr); // Tell the execution engine that the specified global is at the specified // location. This is used internally as functions are JIT'd and as global // variables are laid out in memory. void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) { void *&CurVal = mGlobalAddressMap[GV]; assert((CurVal == 0 || Addr == 0) && "GlobalMapping already established!"); CurVal = Addr; } // This returns the address of the specified global value if it is has // already been codegen'd, otherwise it returns null. void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) { GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV); return ((I != mGlobalAddressMap.end()) ? I->second : NULL); } unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP); // This function converts a Constant* into a GenericValue. The interesting // part is if C is a ConstantExpr. void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result); // Stores the data in @Val of type @Ty at address @Addr. void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr, llvm::Type *Ty); // Recursive function to apply a @Constant value into the specified memory // location @Addr. void InitializeConstantToMemory(const llvm::Constant *C, void *Addr); void emitConstantPool(llvm::MachineConstantPool *MCP); void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI); void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI); void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference, bool MayNeedFarStub); // 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(llvm::Function *F); void *GetLazyFunctionStubIfAvailable(llvm::Function *F) { return mFunctionToLazyStubMap.lookup(F); } void *GetLazyFunctionStub(llvm::Function *F); void updateFunctionStub(const llvm::Function *F); void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure); void *GetPointerToNamedSymbol(const std::string &Name, bool AbortOnFailure); // Return the address of the specified global variable, possibly emitting it // to memory if needed. This is used by the Emitter. void *GetOrEmitGlobalVariable(llvm::GlobalVariable *GV); // This method abstracts memory allocation of global variable so that the // JIT can allocate thread local variables depending on the target. void *GetMemoryForGV(llvm::GlobalVariable *GV); void EmitGlobalVariable(llvm::GlobalVariable *GV); void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference); // This is the equivalent of FunctionToLazyStubMap for external functions. // // TODO(llvm.org): Of course, external functions don't need a lazy stub. // It's actually here to make it more likely that far calls // succeed, but no single stub can guarantee that. I'll // remove this in a subsequent checkin when I actually fix // far calls. // Return a stub for the function at the specified address. void *GetExternalFunctionStub(void *FnAddr); }; } // namespace bcc #endif // BCC_CODEEMITTER_H