JITEmitter.cpp revision 777d2306b36816a53bc1ae1244c0dc7d998ae691
1166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattner//===-- JITEmitter.cpp - Write machine code to executable memory ----------===// 2f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman// 3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// The LLVM Compiler Infrastructure 4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// 54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source 64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details. 7f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman// 8b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//===----------------------------------------------------------------------===// 9bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner// 105be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner// This file defines a MachineCodeEmitter object that is used by the JIT to 115be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner// write machine code to memory and remember where relocatable values are. 12bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner// 13bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner//===----------------------------------------------------------------------===// 14bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner 153785fad56eb90284d4e930d40e9306391630deb1Chris Lattner#define DEBUG_TYPE "jit" 164d326fa9bea5b80147edf14d1521fc41ce315275Chris Lattner#include "JIT.h" 17afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray#include "JITDwarfEmitter.h" 18dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen#include "llvm/Constants.h" 192c0a6a19ef42f2ad547dbc0693e55e082a21ac8bChris Lattner#include "llvm/Module.h" 20dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen#include "llvm/DerivedTypes.h" 21bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner#include "llvm/CodeGen/MachineCodeEmitter.h" 22bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner#include "llvm/CodeGen/MachineFunction.h" 231cc08381f1ab57efdf07248fd5e9fd75ef6f0f99Chris Lattner#include "llvm/CodeGen/MachineConstantPool.h" 2437efe6764568a3829fee26aba532283131d1a104Nate Begeman#include "llvm/CodeGen/MachineJumpTableInfo.h" 25afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray#include "llvm/CodeGen/MachineModuleInfo.h" 265be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner#include "llvm/CodeGen/MachineRelocation.h" 278907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner#include "llvm/ExecutionEngine/JITMemoryManager.h" 28dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen#include "llvm/ExecutionEngine/GenericValue.h" 291cc08381f1ab57efdf07248fd5e9fd75ef6f0f99Chris Lattner#include "llvm/Target/TargetData.h" 305be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner#include "llvm/Target/TargetJITInfo.h" 31acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey#include "llvm/Target/TargetMachine.h" 32afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray#include "llvm/Target/TargetOptions.h" 33551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/Debug.h" 34e7fd553b3be8b95dc0946cd3267bc2db859cd3d8Chris Lattner#include "llvm/Support/MutexGuard.h" 35848b3142addffe24abc775c5a11d5fff8ff73132Nick Lewycky#include "llvm/Support/ValueHandle.h" 36fd58e6e2ecebe92804869586d65b27085110f336Anton Korobeynikov#include "llvm/System/Disassembler.h" 37bc52cada0933f353d30da7b49af9a641bdb2c57dChris Lattner#include "llvm/System/Memory.h" 38dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray#include "llvm/Target/TargetInstrInfo.h" 3947c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng#include "llvm/ADT/SmallPtrSet.h" 40d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman#include "llvm/ADT/SmallVector.h" 41551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/ADT/Statistic.h" 42a00269bc3e97d4e53ed196325ef02e6d1f3d70dcAndrew Lenharth#include <algorithm> 43a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng#ifndef NDEBUG 44a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng#include <iomanip> 45a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng#endif 46c19aadee66b744311afe6e420847e80822a765f2Chris Lattnerusing namespace llvm; 47d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 4836343735cb23680c8f8675deafbbf825d46fd868Chris LattnerSTATISTIC(NumBytes, "Number of bytes of machine code compiled"); 4936343735cb23680c8f8675deafbbf825d46fd868Chris LattnerSTATISTIC(NumRelos, "Number of relocations applied"); 5036343735cb23680c8f8675deafbbf825d46fd868Chris Lattnerstatic JIT *TheJIT = 0; 51bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner 52a00269bc3e97d4e53ed196325ef02e6d1f3d70dcAndrew Lenharth 535426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner//===----------------------------------------------------------------------===// 545426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner// JIT lazy compilation code. 555426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner// 565426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattnernamespace { 57ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer class JITResolverState { 58e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky public: 59e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky typedef std::map<AssertingVH<Function>, void*> FunctionToStubMapTy; 60e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky typedef std::map<void*, Function*> StubToFunctionMapTy; 61e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky typedef std::map<AssertingVH<GlobalValue>, void*> GlobalToIndirectSymMapTy; 62ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer private: 63ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer /// FunctionToStubMap - Keep track of the stub created for a particular 64ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer /// function so that we can reuse them if necessary. 65e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky FunctionToStubMapTy FunctionToStubMap; 66ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer 67ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer /// StubToFunctionMap - Keep track of the function that each stub 68ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer /// corresponds to. 69e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky StubToFunctionMapTy StubToFunctionMap; 7000b16889ab461b7ecef1c91ade101186b7f1fce2Jeff Cohen 715594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng /// GlobalToIndirectSymMap - Keep track of the indirect symbol created for a 72be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng /// particular GlobalVariable so that we can reuse them if necessary. 73e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky GlobalToIndirectSymMapTy GlobalToIndirectSymMap; 74be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 75ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer public: 76e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky FunctionToStubMapTy& getFunctionToStubMap(const MutexGuard& locked) { 77ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer assert(locked.holds(TheJIT->lock)); 78ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer return FunctionToStubMap; 79ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer } 8000b16889ab461b7ecef1c91ade101186b7f1fce2Jeff Cohen 81e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky StubToFunctionMapTy& getStubToFunctionMap(const MutexGuard& locked) { 82ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer assert(locked.holds(TheJIT->lock)); 83ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer return StubToFunctionMap; 84ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer } 85be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 86e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky GlobalToIndirectSymMapTy& getGlobalToIndirectSymMap(const MutexGuard& locked) { 87be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng assert(locked.holds(TheJIT->lock)); 885594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng return GlobalToIndirectSymMap; 89be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng } 90ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer }; 9100b16889ab461b7ecef1c91ade101186b7f1fce2Jeff Cohen 925426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// JITResolver - Keep track of, and resolve, call sites for functions that 935426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// have not yet been compiled. 945426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner class JITResolver { 95e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky typedef JITResolverState::FunctionToStubMapTy FunctionToStubMapTy; 96e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky typedef JITResolverState::StubToFunctionMapTy StubToFunctionMapTy; 97e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky typedef JITResolverState::GlobalToIndirectSymMapTy GlobalToIndirectSymMapTy; 98e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky 995e225588530f641d6627becadffdd7d285bfcdbaChris Lattner /// LazyResolverFn - The target lazy resolver function that we actually 1005e225588530f641d6627becadffdd7d285bfcdbaChris Lattner /// rewrite instructions to use. 1015e225588530f641d6627becadffdd7d285bfcdbaChris Lattner TargetJITInfo::LazyResolverFn LazyResolverFn; 1025e225588530f641d6627becadffdd7d285bfcdbaChris Lattner 103ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer JITResolverState state; 1045426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 105d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner /// ExternalFnToStubMap - This is the equivalent of FunctionToStubMap for 106d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner /// external functions. 107d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner std::map<void*, void*> ExternalFnToStubMap; 1086a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth 1091606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng /// revGOTMap - map addresses to indexes in the GOT 1106a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth std::map<void*, unsigned> revGOTMap; 1116a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth unsigned nextGOTIndex; 1126a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth 113e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner static JITResolver *TheJITResolver; 1145426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner public: 115950a4c40b823cd4f09dc71be635229246dfd6cacDan Gohman explicit JITResolver(JIT &jit) : nextGOTIndex(0) { 116e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner TheJIT = &jit; 117e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner 118e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner LazyResolverFn = jit.getJITInfo().getLazyResolverFunction(JITCompilerFn); 119e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner assert(TheJITResolver == 0 && "Multiple JIT resolvers?"); 120e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner TheJITResolver = this; 121e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner } 122e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner 123e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner ~JITResolver() { 124e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner TheJITResolver = 0; 1255e225588530f641d6627becadffdd7d285bfcdbaChris Lattner } 1265426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 127704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng /// getFunctionStubIfAvailable - This returns a pointer to a function stub 128704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng /// if it has already been created. 129704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng void *getFunctionStubIfAvailable(Function *F); 130704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng 1315426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// getFunctionStub - This returns a pointer to a function stub, creating 132d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman /// one on demand as needed. If empty is true, create a function stub 133d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman /// pointing at address 0, to be filled in later. 134b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman void *getFunctionStub(Function *F); 1355426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 136d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner /// getExternalFunctionStub - Return a stub for the function at the 137d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner /// specified address, created lazily on demand. 138d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner void *getExternalFunctionStub(void *FnAddr); 139d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner 1405594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng /// getGlobalValueIndirectSym - Return an indirect symbol containing the 141c96a8e7df1ffeebc5fb876f5eef380e8547ce14fEvan Cheng /// specified GV address. 1425594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng void *getGlobalValueIndirectSym(GlobalValue *V, void *GVAddress); 143be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 1445e225588530f641d6627becadffdd7d285bfcdbaChris Lattner /// AddCallbackAtLocation - If the target is capable of rewriting an 1455e225588530f641d6627becadffdd7d285bfcdbaChris Lattner /// instruction without the use of a stub, record the location of the use so 1465e225588530f641d6627becadffdd7d285bfcdbaChris Lattner /// we know which function is being used at the location. 1475e225588530f641d6627becadffdd7d285bfcdbaChris Lattner void *AddCallbackAtLocation(Function *F, void *Location) { 148ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer MutexGuard locked(TheJIT->lock); 1495e225588530f641d6627becadffdd7d285bfcdbaChris Lattner /// Get the target-specific JIT resolver function. 150ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer state.getStubToFunctionMap(locked)[Location] = F; 151870286aa33290c00e55ba479a60251c79f3a7911Chris Lattner return (void*)(intptr_t)LazyResolverFn; 1525e225588530f641d6627becadffdd7d285bfcdbaChris Lattner } 153d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 154d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman void getRelocatableGVs(SmallVectorImpl<GlobalValue*> &GVs, 15550cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman SmallVectorImpl<void*> &Ptrs); 15650cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 15750cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman GlobalValue *invalidateStub(void *Stub); 1585e225588530f641d6627becadffdd7d285bfcdbaChris Lattner 1596a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth /// getGOTIndexForAddress - Return a new or existing index in the GOT for 1608907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner /// an address. This function only manages slots, it does not manage the 1616a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth /// contents of the slots or the memory associated with the GOT. 1628907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner unsigned getGOTIndexForAddr(void *addr); 1636a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth 1645426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// JITCompilerFn - This function is called to resolve a stub to a compiled 1655426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// address. If the LLVM Function corresponding to the stub has not yet 1665426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// been compiled, this function compiles it first. 1675426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner static void *JITCompilerFn(void *Stub); 1685426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner }; 1695426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner} 1705426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 171e748401b180d7041738e14d3896ac61ca4bdfcbaChris LattnerJITResolver *JITResolver::TheJITResolver = 0; 1725426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 173704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng/// getFunctionStubIfAvailable - This returns a pointer to a function stub 174704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng/// if it has already been created. 175704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Chengvoid *JITResolver::getFunctionStubIfAvailable(Function *F) { 176704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng MutexGuard locked(TheJIT->lock); 177704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng 178704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng // If we already have a stub for this function, recycle it. 179704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng void *&Stub = state.getFunctionToStubMap(locked)[F]; 180704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng return Stub; 181704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng} 182704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng 1835426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner/// getFunctionStub - This returns a pointer to a function stub, creating 1845426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner/// one on demand as needed. 185b9c6c9bfe410bbea357503872ce662d6838026ceNate Begemanvoid *JITResolver::getFunctionStub(Function *F) { 186ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer MutexGuard locked(TheJIT->lock); 187ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer 1885426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // If we already have a stub for this function, recycle it. 189ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer void *&Stub = state.getFunctionToStubMap(locked)[F]; 1905426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner if (Stub) return Stub; 1915426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 192b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // Call the lazy resolver function unless we are JIT'ing non-lazily, in which 193b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // case we must resolve the symbol now. 194b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman void *Actual = TheJIT->isLazyCompilationDisabled() 195b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman ? (void *)0 : (void *)(intptr_t)LazyResolverFn; 196b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman 197b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // If this is an external declaration, attempt to resolve the address now 198b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // to place in the stub. 19969f9378675b23135043d93aa58300fed3ec41cbfDan Gohman if (F->isDeclaration() && !F->hasNotBeenReadFromBitcode()) { 200b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner Actual = TheJIT->getPointerToFunction(F); 201f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman 20269f9378675b23135043d93aa58300fed3ec41cbfDan Gohman // If we resolved the symbol to a null address (eg. a weak external) 203b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // don't emit a stub. Return a null pointer to the application. If dlsym 204b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // stubs are enabled, not being able to resolve the address is not 205b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // meaningful. 206b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman if (!Actual && !TheJIT->areDlsymStubsEnabled()) return 0; 20769f9378675b23135043d93aa58300fed3ec41cbfDan Gohman } 20869f9378675b23135043d93aa58300fed3ec41cbfDan Gohman 209b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // Codegen a new stub, calling the lazy resolver or the actual address of the 210b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // external function, if it was resolved. 21151cc3c13eac78da242f0518fc42580e48dd5304fNicolas Geoffray Stub = TheJIT->getJITInfo().emitFunctionStub(F, Actual, 212e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner *TheJIT->getCodeEmitter()); 213b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner 214870286aa33290c00e55ba479a60251c79f3a7911Chris Lattner if (Actual != (void*)(intptr_t)LazyResolverFn) { 215b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner // If we are getting the stub for an external function, we really want the 216b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner // address of the stub in the GlobalAddressMap for the JIT, not the address 217b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner // of the external function. 218b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner TheJIT->updateGlobalMapping(F, Stub); 219b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner } 2205426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 221be3ae8e479c02b3045eef8eb18c4dacbd3af14c2Chris Lattner DOUT << "JIT: Stub emitted at [" << Stub << "] for function '" 222832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << F->getName() << "'\n"; 223cb47941556800369216c062dcee8dcab7cd39ee9Chris Lattner 2245426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // Finally, keep track of the stub-to-Function mapping so that the 2255426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // JITCompilerFn knows which function to compile! 226ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer state.getStubToFunctionMap(locked)[Stub] = F; 227d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 228b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // If we are JIT'ing non-lazily but need to call a function that does not 229b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // exist yet, add it to the JIT's work list so that we can fill in the stub 230b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // address later. 231b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman if (!Actual && TheJIT->isLazyCompilationDisabled()) 232b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman if (!F->isDeclaration() || F->hasNotBeenReadFromBitcode()) 233b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman TheJIT->addPendingFunction(F); 234d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 2355426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner return Stub; 2365426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner} 2375426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 2385594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng/// getGlobalValueIndirectSym - Return a lazy pointer containing the specified 239be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng/// GV address. 2405594f120b8880f7c514b0376c4adac1267a0b2b6Evan Chengvoid *JITResolver::getGlobalValueIndirectSym(GlobalValue *GV, void *GVAddress) { 241be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng MutexGuard locked(TheJIT->lock); 242be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 243be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng // If we already have a stub for this global variable, recycle it. 2445594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng void *&IndirectSym = state.getGlobalToIndirectSymMap(locked)[GV]; 2455594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng if (IndirectSym) return IndirectSym; 246be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 247e4d783d584d22d7fcb4cba2a24e0f45f62ed8153Evan Cheng // Otherwise, codegen a new indirect symbol. 2485594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng IndirectSym = TheJIT->getJITInfo().emitGlobalValueIndirectSym(GV, GVAddress, 249c96a8e7df1ffeebc5fb876f5eef380e8547ce14fEvan Cheng *TheJIT->getCodeEmitter()); 250be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 2515594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng DOUT << "JIT: Indirect symbol emitted at [" << IndirectSym << "] for GV '" 252be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng << GV->getName() << "'\n"; 253be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 2545594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng return IndirectSym; 255be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng} 256be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 257d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner/// getExternalFunctionStub - Return a stub for the function at the 258d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner/// specified address, created lazily on demand. 259d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattnervoid *JITResolver::getExternalFunctionStub(void *FnAddr) { 260d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner // If we already have a stub for this function, recycle it. 261d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner void *&Stub = ExternalFnToStubMap[FnAddr]; 262d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner if (Stub) return Stub; 263d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner 26451cc3c13eac78da242f0518fc42580e48dd5304fNicolas Geoffray Stub = TheJIT->getJITInfo().emitFunctionStub(0, FnAddr, 265e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner *TheJIT->getCodeEmitter()); 26655fc28076fa48723bd170e51638b3b5974ca0fa1Evan Cheng 267832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling DOUT << "JIT: Stub emitted at [" << Stub 268832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << "] for external function at '" << FnAddr << "'\n"; 269d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner return Stub; 270d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner} 271d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner 2726a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharthunsigned JITResolver::getGOTIndexForAddr(void* addr) { 2736a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth unsigned idx = revGOTMap[addr]; 2746a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth if (!idx) { 2756a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth idx = ++nextGOTIndex; 2766a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth revGOTMap[addr] = idx; 277366cf29ca537057341ecbad03ab8f9bc52f731e7Evan Cheng DOUT << "JIT: Adding GOT entry " << idx << " for addr [" << addr << "]\n"; 2786a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth } 2796a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth return idx; 2806a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth} 281d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner 282d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begemanvoid JITResolver::getRelocatableGVs(SmallVectorImpl<GlobalValue*> &GVs, 283d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman SmallVectorImpl<void*> &Ptrs) { 284d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman MutexGuard locked(TheJIT->lock); 285d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 286e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky FunctionToStubMapTy &FM = state.getFunctionToStubMap(locked); 287e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky GlobalToIndirectSymMapTy &GM = state.getGlobalToIndirectSymMap(locked); 288d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 289e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky for (FunctionToStubMapTy::iterator i = FM.begin(), e = FM.end(); i != e; ++i){ 290d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman Function *F = i->first; 291d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman if (F->isDeclaration() && F->hasExternalLinkage()) { 292d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman GVs.push_back(i->first); 293d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman Ptrs.push_back(i->second); 294d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman } 295d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman } 296e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky for (GlobalToIndirectSymMapTy::iterator i = GM.begin(), e = GM.end(); 297d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman i != e; ++i) { 298d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman GVs.push_back(i->first); 299d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman Ptrs.push_back(i->second); 300d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman } 301d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman} 302d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 30350cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate BegemanGlobalValue *JITResolver::invalidateStub(void *Stub) { 30450cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman MutexGuard locked(TheJIT->lock); 30550cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 306e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky FunctionToStubMapTy &FM = state.getFunctionToStubMap(locked); 307e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky StubToFunctionMapTy &SM = state.getStubToFunctionMap(locked); 308e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky GlobalToIndirectSymMapTy &GM = state.getGlobalToIndirectSymMap(locked); 30950cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 31050cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // Look up the cheap way first, to see if it's a function stub we are 31150cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // invalidating. If so, remove it from both the forward and reverse maps. 31250cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman if (SM.find(Stub) != SM.end()) { 31350cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman Function *F = SM[Stub]; 31450cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman SM.erase(Stub); 31550cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman FM.erase(F); 31650cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman return F; 31750cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman } 31850cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 319841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman // Otherwise, it might be an indirect symbol stub. Find it and remove it. 320e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky for (GlobalToIndirectSymMapTy::iterator i = GM.begin(), e = GM.end(); 32150cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman i != e; ++i) { 32250cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman if (i->second != Stub) 32350cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman continue; 32450cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman GlobalValue *GV = i->first; 32550cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman GM.erase(i); 32650cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman return GV; 32750cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman } 32850cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 329841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman // Lastly, check to see if it's in the ExternalFnToStubMap. 330841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman for (std::map<void *, void *>::iterator i = ExternalFnToStubMap.begin(), 331841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman e = ExternalFnToStubMap.end(); i != e; ++i) { 332841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman if (i->second != Stub) 333841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman continue; 334841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman ExternalFnToStubMap.erase(i); 335841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman break; 336841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman } 337841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman 33850cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman return 0; 33950cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman} 34050cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 3415426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner/// JITCompilerFn - This function is called when a lazy compilation stub has 3425426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner/// been entered. It looks up which function this stub corresponds to, compiles 3435426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner/// it if necessary, then returns the resultant function pointer. 3445426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattnervoid *JITResolver::JITCompilerFn(void *Stub) { 345e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner JITResolver &JR = *TheJITResolver; 346dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray 347dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray Function* F = 0; 348dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray void* ActualPtr = 0; 349dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray 350dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray { 351dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray // Only lock for getting the Function. The call getPointerToFunction made 352dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray // in this function might trigger function materializing, which requires 353dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray // JIT lock to be unlocked. 354dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray MutexGuard locked(TheJIT->lock); 355dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray 356dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray // The address given to us for the stub may not be exactly right, it might be 357dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray // a little bit after the stub. As such, use upper_bound to find it. 358e2bcf13be5e7b9b9ea103c5546dab51f5cac9cb0Nick Lewycky StubToFunctionMapTy::iterator I = 359dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray JR.state.getStubToFunctionMap(locked).upper_bound(Stub); 360dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray assert(I != JR.state.getStubToFunctionMap(locked).begin() && 361dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray "This is not a known stub!"); 362dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray F = (--I)->second; 363dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray ActualPtr = I->first; 364dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray } 3655426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 3669da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // If we have already code generated the function, just return the address. 3679da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng void *Result = TheJIT->getPointerToGlobalIfAvailable(F); 3689da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng 3699da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng if (!Result) { 3709da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // Otherwise we don't have it, do lazy compilation now. 3719da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng 3729da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // If lazy compilation is disabled, emit a useful error message and abort. 3739da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng if (TheJIT->isLazyCompilationDisabled()) { 3749da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng cerr << "LLVM JIT requested to do lazy compilation of function '" 3759da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng << F->getName() << "' when lazy compiles are disabled!\n"; 3769da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng abort(); 3779da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng } 3789cab56d59e2ed6af5fb5137a6e50d4bf915eaccfChris Lattner 3799da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // We might like to remove the stub from the StubToFunction map. 3809da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // We can't do that! Multiple threads could be stuck, waiting to acquire the 3819da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // lock above. As soon as the 1st function finishes compiling the function, 3829da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // the next one will be released, and needs to be able to find the function 3839da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // it needs to call. 3849da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng //JR.state.getStubToFunctionMap(locked).erase(I); 3859da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng 3869da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng DOUT << "JIT: Lazily resolving function '" << F->getName() 3879da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng << "' In stub ptr = " << Stub << " actual ptr = " 388dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray << ActualPtr << "\n"; 3899da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng 3909da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng Result = TheJIT->getPointerToFunction(F); 3919da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng } 392dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray 393dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray // Reacquire the lock to erase the stub in the map. 394dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray MutexGuard locked(TheJIT->lock); 3955426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 3965426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // We don't need to reuse this stub in the future, as F is now compiled. 397ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer JR.state.getFunctionToStubMap(locked).erase(F); 3985426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 3995426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // FIXME: We could rewrite all references to this stub if we knew them. 4006a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth 401d29b6aa608d69f19b57ebd2ae630b040b1c4951dJeff Cohen // What we will do is set the compiled function address to map to the 402d29b6aa608d69f19b57ebd2ae630b040b1c4951dJeff Cohen // same GOT entry as the stub so that later clients may update the GOT 4036a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth // if they see it still using the stub address. 4046a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth // Note: this is done so the Resolver doesn't have to manage GOT memory 4056a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth // Do this without allocating map space if the target isn't using a GOT 4066a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth if(JR.revGOTMap.find(Stub) != JR.revGOTMap.end()) 4076a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth JR.revGOTMap[Result] = JR.revGOTMap[Stub]; 4086a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth 4095426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner return Result; 4105426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner} 4115426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 4128ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner//===----------------------------------------------------------------------===// 4138ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// Function Index Support 4148ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4158ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// On MacOS we generate an index of currently JIT'd functions so that 4168ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// performance tools can determine a symbol name and accurate code range for a 4178ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// PC value. Because performance tools are generally asynchronous, the code 4188ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// below is written with the hope that it could be interrupted at any time and 4198ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// have useful answers. However, we don't go crazy with atomic operations, we 4208ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// just do a "reasonable effort". 4218ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#ifdef __APPLE__ 422bdb6ca178cfbe2490a058deabce7847a05f55db7Evan Cheng#define ENABLE_JIT_SYMBOL_TABLE 0 4238ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#endif 4248ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4258ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner/// JitSymbolEntry - Each function that is JIT compiled results in one of these 4268ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner/// being added to an array of symbols. This indicates the name of the function 4278ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner/// as well as the address range it occupies. This allows the client to map 4288ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner/// from a PC value to the name of the function. 4298ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattnerstruct JitSymbolEntry { 4308ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner const char *FnName; // FnName - a strdup'd string. 4318ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner void *FnStart; 4328ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner intptr_t FnSize; 4338ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner}; 4348ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4358ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4368ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattnerstruct JitSymbolTable { 4378ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// NextPtr - This forms a linked list of JitSymbolTable entries. This 4388ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// pointer is not used right now, but might be used in the future. Consider 4398ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// it reserved for future use. 4408ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolTable *NextPtr; 4418ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4428ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// Symbols - This is an array of JitSymbolEntry entries. Only the first 4438ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// 'NumSymbols' symbols are valid. 4448ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolEntry *Symbols; 4458ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4468ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// NumSymbols - This indicates the number entries in the Symbols array that 4478ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// are valid. 4488ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner unsigned NumSymbols; 4498ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4508ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// NumAllocated - This indicates the amount of space we have in the Symbols 4518ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// array. This is a private field that should not be read by external tools. 4528ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner unsigned NumAllocated; 4538ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner}; 4548ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4558ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#if ENABLE_JIT_SYMBOL_TABLE 4568ac66c122b099bc3eab858bfc18f3cb342efc818Chris LattnerJitSymbolTable *__jitSymbolTable; 4578ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#endif 4588ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4598ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattnerstatic void AddFunctionToSymbolTable(const char *FnName, 4608ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner void *FnStart, intptr_t FnSize) { 4618ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner assert(FnName != 0 && FnStart != 0 && "Bad symbol to add"); 4628ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolTable **SymTabPtrPtr = 0; 4638ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#if !ENABLE_JIT_SYMBOL_TABLE 4648ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner return; 4658ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#else 4668ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner SymTabPtrPtr = &__jitSymbolTable; 4678ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#endif 4688ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4698ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // If this is the first entry in the symbol table, add the JitSymbolTable 4708ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // index. 4718ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner if (*SymTabPtrPtr == 0) { 4728ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolTable *New = new JitSymbolTable(); 4738ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner New->NextPtr = 0; 4748ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner New->Symbols = 0; 4758ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner New->NumSymbols = 0; 4768ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner New->NumAllocated = 0; 4778ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner *SymTabPtrPtr = New; 4788ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner } 4798ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4808ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolTable *SymTabPtr = *SymTabPtrPtr; 4818ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4828ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // If we have space in the table, reallocate the table. 4838ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner if (SymTabPtr->NumSymbols >= SymTabPtr->NumAllocated) { 4848ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // If we don't have space, reallocate the table. 4853b374489041ac28153c84194dda45e182d8939fcChris Lattner unsigned NewSize = std::max(64U, SymTabPtr->NumAllocated*2); 4868ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolEntry *NewSymbols = new JitSymbolEntry[NewSize]; 4878ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolEntry *OldSymbols = SymTabPtr->Symbols; 4888ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4898ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Copy the old entries over. 490d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman memcpy(NewSymbols, OldSymbols, SymTabPtr->NumSymbols*sizeof(OldSymbols[0])); 4918ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4928ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Swap the new symbols in, delete the old ones. 4938ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner SymTabPtr->Symbols = NewSymbols; 4943b374489041ac28153c84194dda45e182d8939fcChris Lattner SymTabPtr->NumAllocated = NewSize; 4958ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner delete [] OldSymbols; 4968ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner } 4978ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4988ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Otherwise, we have enough space, just tack it onto the end of the array. 4998ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolEntry &Entry = SymTabPtr->Symbols[SymTabPtr->NumSymbols]; 5008ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner Entry.FnName = strdup(FnName); 5018ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner Entry.FnStart = FnStart; 5028ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner Entry.FnSize = FnSize; 5038ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner ++SymTabPtr->NumSymbols; 5048ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner} 5058ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 5068ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattnerstatic void RemoveFunctionFromSymbolTable(void *FnStart) { 5078ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner assert(FnStart && "Invalid function pointer"); 5088ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolTable **SymTabPtrPtr = 0; 5098ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#if !ENABLE_JIT_SYMBOL_TABLE 5108ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner return; 5118ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#else 5128ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner SymTabPtrPtr = &__jitSymbolTable; 5138ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#endif 5148ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 5158ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolTable *SymTabPtr = *SymTabPtrPtr; 5168ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolEntry *Symbols = SymTabPtr->Symbols; 5178ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 5188ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Scan the table to find its index. The table is not sorted, so do a linear 5198ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // scan. 5208ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner unsigned Index; 5218ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner for (Index = 0; Symbols[Index].FnStart != FnStart; ++Index) 5228ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner assert(Index != SymTabPtr->NumSymbols && "Didn't find function!"); 5238ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 5248ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Once we have an index, we know to nuke this entry, overwrite it with the 5258ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // entry at the end of the array, making the last entry redundant. 5268ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner const char *OldName = Symbols[Index].FnName; 5278ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner Symbols[Index] = Symbols[SymTabPtr->NumSymbols-1]; 5288ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner free((void*)OldName); 5298ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 5308ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Drop the number of symbols in the table. 5318ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner --SymTabPtr->NumSymbols; 5328ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 5338ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Finally, if we deleted the final symbol, deallocate the table itself. 534f44085a86a3f3cb743fb8822108d8360dd094539Nate Begeman if (SymTabPtr->NumSymbols != 0) 5358ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner return; 5368ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 5378ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner *SymTabPtrPtr = 0; 5388ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner delete [] Symbols; 5398ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner delete SymTabPtr; 5408ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner} 5415426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 5425426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner//===----------------------------------------------------------------------===// 543166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattner// JITEmitter code. 5445426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner// 545688506de24f04682f9d8563a7d20ab15ab85340bChris Lattnernamespace { 546166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattner /// JITEmitter - The JIT implementation of the MachineCodeEmitter, which is 547166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattner /// used to output functions to memory for execution. 548166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattner class JITEmitter : public MachineCodeEmitter { 5498907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner JITMemoryManager *MemMgr; 550688506de24f04682f9d8563a7d20ab15ab85340bChris Lattner 5516125fddb52c3d821a4e4c000cbd210428b0009f6Chris Lattner // When outputting a function stub in the context of some other function, we 55243b429b05989075b60693d57395c99b0ad789f8dChris Lattner // save BufferBegin/BufferEnd/CurBufferPtr here. 55343b429b05989075b60693d57395c99b0ad789f8dChris Lattner unsigned char *SavedBufferBegin, *SavedBufferEnd, *SavedCurBufferPtr; 554bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner 5555be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner /// Relocations - These are the relocations that the function needs, as 5565be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner /// emitted. 5575be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner std::vector<MachineRelocation> Relocations; 558b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner 559b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner /// MBBLocations - This vector is a mapping from MBB ID's to their address. 560b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner /// It is filled in by the StartMachineBasicBlock callback and queried by 561b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner /// the getMachineBasicBlockAddress callback. 5625788d1a169db3346a612a13113348d2709bdd15bEvan Cheng std::vector<uintptr_t> MBBLocations; 56316ec33c6ef630730ad55a4af7242c658e1efb8b3Andrew Lenharth 564239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner /// ConstantPool - The constant pool for the current function. 565239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner /// 566239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner MachineConstantPool *ConstantPool; 567239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner 568239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner /// ConstantPoolBase - A pointer to the first entry in the constant pool. 569239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner /// 570239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner void *ConstantPoolBase; 57137efe6764568a3829fee26aba532283131d1a104Nate Begeman 5721606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng /// ConstPoolAddresses - Addresses of individual constant pool entries. 5731606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng /// 5741606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng SmallVector<uintptr_t, 8> ConstPoolAddresses; 5751606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng 576019f851ab26511c089e41b61901f743e75f90714Nate Begeman /// JumpTable - The jump tables for the current function. 57737efe6764568a3829fee26aba532283131d1a104Nate Begeman /// 57837efe6764568a3829fee26aba532283131d1a104Nate Begeman MachineJumpTableInfo *JumpTable; 57937efe6764568a3829fee26aba532283131d1a104Nate Begeman 58037efe6764568a3829fee26aba532283131d1a104Nate Begeman /// JumpTableBase - A pointer to the first entry in the jump table. 58137efe6764568a3829fee26aba532283131d1a104Nate Begeman /// 58237efe6764568a3829fee26aba532283131d1a104Nate Begeman void *JumpTableBase; 5832a3e08b5961353fa3faeadf81f481ae9f5463427Evan Cheng 584e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner /// Resolver - This contains info about the currently resolved functions. 585e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner JITResolver Resolver; 586afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 587afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray /// DE - The dwarf emitter for the jit. 588afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray JITDwarfEmitter *DE; 589afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 590afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray /// LabelLocations - This vector is a mapping from Label ID's to their 591afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray /// address. 5925788d1a169db3346a612a13113348d2709bdd15bEvan Cheng std::vector<uintptr_t> LabelLocations; 593afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 594afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray /// MMI - Machine module info for exception informations 595afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray MachineModuleInfo* MMI; 596afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 597dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // GVSet - a set to keep track of which globals have been seen 59847c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng SmallPtrSet<const GlobalVariable*, 8> GVSet; 599dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 60050cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // CurFn - The llvm function being emitted. Only valid during 60150cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // finishFunction(). 60250cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman const Function *CurFn; 60350cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 60450cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // CurFnStubUses - For a given Function, a vector of stubs that it 60550cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // references. This facilitates the JIT detecting that a stub is no 60650cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // longer used, so that it may be deallocated. 60750cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman DenseMap<const Function *, SmallVector<void*, 1> > CurFnStubUses; 60850cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 60950cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // StubFnRefs - For a given pointer to a stub, a set of Functions which 61050cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // reference the stub. When the count of a stub's references drops to zero, 61150cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // the stub is unused. 61250cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman DenseMap<void *, SmallPtrSet<const Function*, 1> > StubFnRefs; 61350cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 614841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman // ExtFnStubs - A map of external function names to stubs which have entries 615841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman // in the JITResolver's ExternalFnToStubMap. 616841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman StringMap<void *> ExtFnStubs; 617841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman 618e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner public: 61950cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman JITEmitter(JIT &jit, JITMemoryManager *JMM) : Resolver(jit), CurFn(0) { 6209f2f142d255bc96f109dd5c6524a485937b1f3a1Chris Lattner MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager(); 6218907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner if (jit.getJITInfo().needsGOT()) { 6228907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner MemMgr->AllocateGOT(); 6238907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner DOUT << "JIT is managing a GOT\n"; 6248907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner } 625afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 626afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray if (ExceptionHandling) DE = new JITDwarfEmitter(jit); 6278907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner } 6288907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner ~JITEmitter() { 6298907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner delete MemMgr; 630afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray if (ExceptionHandling) delete DE; 63116ec33c6ef630730ad55a4af7242c658e1efb8b3Andrew Lenharth } 632a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng 633a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng /// classof - Methods for support type inquiry through isa, cast, and 634a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng /// dyn_cast: 635a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng /// 636a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng static inline bool classof(const JITEmitter*) { return true; } 637a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng static inline bool classof(const MachineCodeEmitter*) { return true; } 638e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner 639e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner JITResolver &getJITResolver() { return Resolver; } 640bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner 641bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner virtual void startFunction(MachineFunction &F); 64243b429b05989075b60693d57395c99b0ad789f8dChris Lattner virtual bool finishFunction(MachineFunction &F); 643f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 644f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner void emitConstantPool(MachineConstantPool *MCP); 645f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner void initJumpTableInfo(MachineJumpTableInfo *MJTI); 646b92767afd442a8363a8696e54880ee31c5d48c1eJim Laskey void emitJumpTableInfo(MachineJumpTableInfo *MJTI); 647f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 648ce4a70bd7608861e104b04265a0c71e5df8ecefeEvan Cheng virtual void startGVStub(const GlobalValue* GV, unsigned StubSize, 64951cc3c13eac78da242f0518fc42580e48dd5304fNicolas Geoffray unsigned Alignment = 1); 650d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman virtual void startGVStub(const GlobalValue* GV, void *Buffer, 651d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman unsigned StubSize); 652ce4a70bd7608861e104b04265a0c71e5df8ecefeEvan Cheng virtual void* finishGVStub(const GlobalValue *GV); 653bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner 654cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes /// allocateSpace - Reserves space in the current block if any, or 655cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes /// allocate a new one of the given size. 6565788d1a169db3346a612a13113348d2709bdd15bEvan Cheng virtual void *allocateSpace(uintptr_t Size, unsigned Alignment); 657cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes 6585be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner virtual void addRelocation(const MachineRelocation &MR) { 6595be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner Relocations.push_back(MR); 6605be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner } 661b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner 662b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { 663b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner if (MBBLocations.size() <= (unsigned)MBB->getNumber()) 664b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner MBBLocations.resize((MBB->getNumber()+1)*2); 665b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner MBBLocations[MBB->getNumber()] = getCurrentPCValue(); 666366cf29ca537057341ecbad03ab8f9bc52f731e7Evan Cheng DOUT << "JIT: Emitting BB" << MBB->getNumber() << " at [" 667366cf29ca537057341ecbad03ab8f9bc52f731e7Evan Cheng << (void*) getCurrentPCValue() << "]\n"; 668b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner } 669b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner 6705788d1a169db3346a612a13113348d2709bdd15bEvan Cheng virtual uintptr_t getConstantPoolEntryAddress(unsigned Entry) const; 6715788d1a169db3346a612a13113348d2709bdd15bEvan Cheng virtual uintptr_t getJumpTableEntryAddress(unsigned Entry) const; 6722a3e08b5961353fa3faeadf81f481ae9f5463427Evan Cheng 6735788d1a169db3346a612a13113348d2709bdd15bEvan Cheng virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { 674b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner assert(MBBLocations.size() > (unsigned)MBB->getNumber() && 675b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner MBBLocations[MBB->getNumber()] && "MBB not emitted!"); 676b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner return MBBLocations[MBB->getNumber()]; 677b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner } 6785be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner 679e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner /// deallocateMemForFunction - Deallocate all memory for the specified 680e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner /// function body. 68150cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman void deallocateMemForFunction(Function *F); 682841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman 683841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman /// AddStubToCurrentFunction - Mark the current function being JIT'd as 684841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman /// using the stub at the specified address. Allows 685841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman /// deallocateMemForFunction to also remove stubs no longer referenced. 686841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman void AddStubToCurrentFunction(void *Stub); 687841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman 688841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman /// getExternalFnStubs - Accessor for the JIT to find stubs emitted for 689841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman /// MachineRelocations that reference external functions by name. 690841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman const StringMap<void*> &getExternalFnStubs() const { return ExtFnStubs; } 691afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 692afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray virtual void emitLabel(uint64_t LabelID) { 693afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray if (LabelLocations.size() <= LabelID) 694afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray LabelLocations.resize((LabelID+1)*2); 695afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray LabelLocations[LabelID] = getCurrentPCValue(); 696afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray } 697afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 6985788d1a169db3346a612a13113348d2709bdd15bEvan Cheng virtual uintptr_t getLabelAddress(uint64_t LabelID) const { 699afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray assert(LabelLocations.size() > (unsigned)LabelID && 700afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray LabelLocations[LabelID] && "Label not emitted!"); 701afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray return LabelLocations[LabelID]; 702afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray } 703afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 704afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray virtual void setModuleInfo(MachineModuleInfo* Info) { 705afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray MMI = Info; 706afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray if (ExceptionHandling) DE->setModuleInfo(Info); 707afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray } 708afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 709cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach void setMemoryExecutable(void) { 710cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach MemMgr->setMemoryExecutable(); 711cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach } 712d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 713d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman JITMemoryManager *getMemMgr(void) const { return MemMgr; } 714cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach 7155426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner private: 7165e225588530f641d6627becadffdd7d285bfcdbaChris Lattner void *getPointerToGlobal(GlobalValue *GV, void *Reference, bool NoNeedStub); 7175594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng void *getPointerToGVIndirectSym(GlobalValue *V, void *Reference, 718e4d783d584d22d7fcb4cba2a24e0f45f62ed8153Evan Cheng bool NoNeedStub); 719dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned addSizeOfGlobal(const GlobalVariable *GV, unsigned Size); 720dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned addSizeOfGlobalsInConstantVal(const Constant *C, unsigned Size); 721dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned addSizeOfGlobalsInInitializer(const Constant *Init, unsigned Size); 722dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned GetSizeOfGlobalsInBytes(MachineFunction &MF); 723bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner }; 724bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner} 725bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner 726166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattnervoid *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference, 727166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattner bool DoesntNeedStub) { 728d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) 7295426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner return TheJIT->getOrEmitGlobalVariable(GV); 730d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 73118e045983757a7d2bae482d2abe444a5bb3ed134Chris Lattner if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) 73219e861a4ffb896f16a691d5ac869e894df3cd464Anton Korobeynikov return TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false)); 7335426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 7345426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // If we have already compiled the function, return a pointer to its body. 7355426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner Function *F = cast<Function>(V); 736704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng void *ResultPtr; 73750cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman if (!DoesntNeedStub && !TheJIT->isLazyCompilationDisabled()) { 738704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng // Return the function stub if it's already created. 739704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng ResultPtr = Resolver.getFunctionStubIfAvailable(F); 74050cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman if (ResultPtr) 74150cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman AddStubToCurrentFunction(ResultPtr); 74250cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman } else { 743704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng ResultPtr = TheJIT->getPointerToGlobalIfAvailable(F); 74450cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman } 7455426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner if (ResultPtr) return ResultPtr; 7465426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 747d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman // If this is an external function pointer, we can force the JIT to 748b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // 'compile' it, which really just adds it to the map. In dlsym mode, 749b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // external functions are forced through a stub, regardless of reloc type. 750b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman if (F->isDeclaration() && !F->hasNotBeenReadFromBitcode() && 751b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman DoesntNeedStub && !TheJIT->areDlsymStubsEnabled()) 752d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman return TheJIT->getPointerToFunction(F); 753d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 7545e225588530f641d6627becadffdd7d285bfcdbaChris Lattner // Okay, the function has not been compiled yet, if the target callback 7555e225588530f641d6627becadffdd7d285bfcdbaChris Lattner // mechanism is capable of rewriting the instruction directly, prefer to do 756b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // that instead of emitting a stub. This uses the lazy resolver, so is not 757b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // legal if lazy compilation is disabled. 758b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman if (DoesntNeedStub && !TheJIT->isLazyCompilationDisabled()) 759e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner return Resolver.AddCallbackAtLocation(F, Reference); 7605e225588530f641d6627becadffdd7d285bfcdbaChris Lattner 761b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // Otherwise, we have to emit a stub. 76250cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman void *StubAddr = Resolver.getFunctionStub(F); 76350cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 76450cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // Add the stub to the current function's list of referenced stubs, so we can 765b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // deallocate them if the current function is ever freed. It's possible to 766b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // return null from getFunctionStub in the case of a weak extern that fails 767b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman // to resolve. 768b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman if (StubAddr) 769b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman AddStubToCurrentFunction(StubAddr); 770b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman 77150cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman return StubAddr; 7725426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner} 7735426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 7745594f120b8880f7c514b0376c4adac1267a0b2b6Evan Chengvoid *JITEmitter::getPointerToGVIndirectSym(GlobalValue *V, void *Reference, 775e4d783d584d22d7fcb4cba2a24e0f45f62ed8153Evan Cheng bool NoNeedStub) { 77650cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // Make sure GV is emitted first, and create a stub containing the fully 77750cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // resolved address. 778be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng void *GVAddress = getPointerToGlobal(V, Reference, true); 77950cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman void *StubAddr = Resolver.getGlobalValueIndirectSym(V, GVAddress); 78050cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 78150cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // Add the stub to the current function's list of referenced stubs, so we can 78250cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // deallocate them if the current function is ever freed. 78350cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman AddStubToCurrentFunction(StubAddr); 78450cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 78550cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman return StubAddr; 78650cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman} 78750cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 78850cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begemanvoid JITEmitter::AddStubToCurrentFunction(void *StubAddr) { 78950cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman if (!TheJIT->areDlsymStubsEnabled()) 79050cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman return; 79150cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 79250cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman assert(CurFn && "Stub added to current function, but current function is 0!"); 79350cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 79450cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman SmallVectorImpl<void*> &StubsUsed = CurFnStubUses[CurFn]; 79550cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman StubsUsed.push_back(StubAddr); 79650cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 79750cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman SmallPtrSet<const Function *, 1> &FnRefs = StubFnRefs[StubAddr]; 79850cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman FnRefs.insert(CurFn); 799be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng} 800be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 8011606e8e4cd937e6de6681f686c266cf61722d972Evan Chengstatic unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP, 8021606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng const TargetData *TD) { 803dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants(); 804dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray if (Constants.empty()) return 0; 805dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 8061606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng unsigned Size = 0; 8071606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng for (unsigned i = 0, e = Constants.size(); i != e; ++i) { 8081606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng MachineConstantPoolEntry CPE = Constants[i]; 8091606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng unsigned AlignMask = CPE.getAlignment() - 1; 8101606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng Size = (Size + AlignMask) & ~AlignMask; 8111606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng const Type *Ty = CPE.getType(); 812777d2306b36816a53bc1ae1244c0dc7d998ae691Duncan Sands Size += TD->getTypeAllocSize(Ty); 8131606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng } 814dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray return Size; 815dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray} 816dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 817dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffraystatic unsigned GetJumpTableSizeInBytes(MachineJumpTableInfo *MJTI) { 818dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 819dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray if (JT.empty()) return 0; 820dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 821dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray unsigned NumEntries = 0; 822dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray for (unsigned i = 0, e = JT.size(); i != e; ++i) 823dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray NumEntries += JT[i].MBBs.size(); 824dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 825dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray unsigned EntrySize = MJTI->getEntrySize(); 826dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 827dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray return NumEntries * EntrySize; 828dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray} 829dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 830580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffraystatic uintptr_t RoundUpToAlign(uintptr_t Size, unsigned Alignment) { 831dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray if (Alignment == 0) Alignment = 1; 832580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray // Since we do not know where the buffer will be allocated, be pessimistic. 833580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray return Size + Alignment; 834dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray} 835be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 836dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// addSizeOfGlobal - add the size of the global (plus any alignment padding) 837dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// into the running total Size. 838dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 839dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesenunsigned JITEmitter::addSizeOfGlobal(const GlobalVariable *GV, unsigned Size) { 840dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen const Type *ElTy = GV->getType()->getElementType(); 841777d2306b36816a53bc1ae1244c0dc7d998ae691Duncan Sands size_t GVSize = (size_t)TheJIT->getTargetData()->getTypeAllocSize(ElTy); 842dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen size_t GVAlign = 843dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen (size_t)TheJIT->getTargetData()->getPreferredAlignment(GV); 844eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: Adding in size " << GVSize << " alignment " << GVAlign; 845dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen DEBUG(GV->dump()); 846dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // Assume code section ends with worst possible alignment, so first 847dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // variable needs maximal padding. 848dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (Size==0) 849dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = 1; 850dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = ((Size+GVAlign-1)/GVAlign)*GVAlign; 851dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size += GVSize; 852dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen return Size; 853dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen} 854dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 855dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// addSizeOfGlobalsInConstantVal - find any globals that we haven't seen yet 856dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// but are referenced from the constant; put them in GVSet and add their 857dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// size into the running total Size. 858dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 859dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesenunsigned JITEmitter::addSizeOfGlobalsInConstantVal(const Constant *C, 860dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned Size) { 861dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // If its undefined, return the garbage. 862dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (isa<UndefValue>(C)) 863dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen return Size; 864dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 865dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // If the value is a ConstantExpr 866dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { 867dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Constant *Op0 = CE->getOperand(0); 868dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen switch (CE->getOpcode()) { 869dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::GetElementPtr: 870dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::Trunc: 871dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::ZExt: 872dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::SExt: 873dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::FPTrunc: 874dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::FPExt: 875dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::UIToFP: 876dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::SIToFP: 877dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::FPToUI: 878dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::FPToSI: 879dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::PtrToInt: 880dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::IntToPtr: 881dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::BitCast: { 882dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobalsInConstantVal(Op0, Size); 883dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen break; 884dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 885dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::Add: 886dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::Sub: 887dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::Mul: 888dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::UDiv: 889dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::SDiv: 890dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::URem: 891dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::SRem: 892dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::And: 893dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::Or: 894dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::Xor: { 895dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobalsInConstantVal(Op0, Size); 896dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobalsInConstantVal(CE->getOperand(1), Size); 897dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen break; 898dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 899dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen default: { 900dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen cerr << "ConstantExpr not handled: " << *CE << "\n"; 901dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen abort(); 902dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 903dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 904dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 905dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 906dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (C->getType()->getTypeID() == Type::PointerTyID) 907dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(C)) 90847c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng if (GVSet.insert(GV)) 909dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobal(GV, Size); 910dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 911dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen return Size; 912dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen} 913dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 914dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// addSizeOfGLobalsInInitializer - handle any globals that we haven't seen yet 915dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// but are referenced from the given initializer. 916dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 917dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesenunsigned JITEmitter::addSizeOfGlobalsInInitializer(const Constant *Init, 918dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned Size) { 919dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (!isa<UndefValue>(Init) && 920dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen !isa<ConstantVector>(Init) && 921dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen !isa<ConstantAggregateZero>(Init) && 922dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen !isa<ConstantArray>(Init) && 923dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen !isa<ConstantStruct>(Init) && 924dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Init->getType()->isFirstClassType()) 925dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobalsInConstantVal(Init, Size); 926dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen return Size; 927dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen} 928dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 929dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// GetSizeOfGlobalsInBytes - walk the code for the function, looking for 930dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// globals; then walk the initializers of those globals looking for more. 931dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// If their size has not been considered yet, add it into the running total 932dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// Size. 933dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 934dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesenunsigned JITEmitter::GetSizeOfGlobalsInBytes(MachineFunction &MF) { 935dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned Size = 0; 936dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen GVSet.clear(); 937dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 938dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); 939dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen MBB != E; ++MBB) { 940dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); 941dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen I != E; ++I) { 942dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen const TargetInstrDesc &Desc = I->getDesc(); 943dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen const MachineInstr &MI = *I; 944dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned NumOps = Desc.getNumOperands(); 945dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen for (unsigned CurOp = 0; CurOp < NumOps; CurOp++) { 946dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen const MachineOperand &MO = MI.getOperand(CurOp); 947d735b8019b0f297d7c14b55adcd887af24d8e602Dan Gohman if (MO.isGlobal()) { 948dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen GlobalValue* V = MO.getGlobal(); 949dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen const GlobalVariable *GV = dyn_cast<const GlobalVariable>(V); 950dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (!GV) 951dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen continue; 952dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // If seen in previous function, it will have an entry here. 953dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (TheJIT->getPointerToGlobalIfAvailable(GV)) 954dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen continue; 955dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // If seen earlier in this function, it will have an entry here. 956dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // FIXME: it should be possible to combine these tables, by 957dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // assuming the addresses of the new globals in this module 958dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // start at 0 (or something) and adjusting them after codegen 959dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // complete. Another possibility is to grab a marker bit in GV. 96047c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng if (GVSet.insert(GV)) 961dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // A variable as yet unseen. Add in its size. 962dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobal(GV, Size); 963dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 964dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 965dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 966dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 967eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: About to look through initializers\n"; 968dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // Look for more globals that are referenced only from initializers. 969dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // GVSet.end is computed each time because the set can grow as we go. 97047c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng for (SmallPtrSet<const GlobalVariable *, 8>::iterator I = GVSet.begin(); 971dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen I != GVSet.end(); I++) { 972dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen const GlobalVariable* GV = *I; 973dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (GV->hasInitializer()) 974dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobalsInInitializer(GV->getInitializer(), Size); 975dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 976dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 977dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen return Size; 978dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen} 979dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 980166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattnervoid JITEmitter::startFunction(MachineFunction &F) { 981eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: Starting CodeGen of Function " 982eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng << F.getFunction()->getName() << "\n"; 983eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng 984dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray uintptr_t ActualSize = 0; 985cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach // Set the memory writable, if it's not already 986cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach MemMgr->setMemoryWritable(); 9875913e6c5dbaff88ac00d5e679382abc72323831aNicolas Geoffray if (MemMgr->NeedsExactSize()) { 988eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: ExactSize\n"; 989dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray const TargetInstrInfo* TII = F.getTarget().getInstrInfo(); 990dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray MachineJumpTableInfo *MJTI = F.getJumpTableInfo(); 991dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray MachineConstantPool *MCP = F.getConstantPool(); 992dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 993dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Ensure the constant pool/jump table info is at least 4-byte aligned. 994580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray ActualSize = RoundUpToAlign(ActualSize, 16); 995dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 996dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Add the alignment of the constant pool 9971606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng ActualSize = RoundUpToAlign(ActualSize, MCP->getConstantPoolAlignment()); 998dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 999dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Add the constant pool size 10001606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng ActualSize += GetConstantPoolSizeInBytes(MCP, TheJIT->getTargetData()); 1001dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 1002dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Add the aligment of the jump table info 1003580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray ActualSize = RoundUpToAlign(ActualSize, MJTI->getAlignment()); 1004dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 1005dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Add the jump table size 1006dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray ActualSize += GetJumpTableSizeInBytes(MJTI); 1007dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 1008dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Add the alignment for the function 1009580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray ActualSize = RoundUpToAlign(ActualSize, 1010580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray std::max(F.getFunction()->getAlignment(), 8U)); 1011dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 1012dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Add the function size 1013dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray ActualSize += TII->GetFunctionSizeInBytes(F); 1014dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 1015eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: ActualSize before globals " << ActualSize << "\n"; 1016dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // Add the size of the globals that will be allocated after this function. 1017dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // These are all the ones referenced from this function that were not 1018dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // previously allocated. 1019dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen ActualSize += GetSizeOfGlobalsInBytes(F); 1020eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: ActualSize after globals " << ActualSize << "\n"; 1021dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray } 1022dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 10238907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(), 10248907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner ActualSize); 1025e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner BufferEnd = BufferBegin+ActualSize; 1026f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 10279a1e9b91407f4752ff3de392d60a6cf3f1dcc37dEvan Cheng // Ensure the constant pool/jump table info is at least 4-byte aligned. 10289a1e9b91407f4752ff3de392d60a6cf3f1dcc37dEvan Cheng emitAlignment(16); 10299a1e9b91407f4752ff3de392d60a6cf3f1dcc37dEvan Cheng 1030f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner emitConstantPool(F.getConstantPool()); 1031f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner initJumpTableInfo(F.getJumpTableInfo()); 1032f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 1033f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner // About to start emitting the machine code for the function. 10340eb4d6b52e1b5db9a4c86e5a954356ae3507a287Chris Lattner emitAlignment(std::max(F.getFunction()->getAlignment(), 8U)); 1035f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr); 103655fc28076fa48723bd170e51638b3b5974ca0fa1Evan Cheng 1037b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner MBBLocations.clear(); 1038bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner} 1039bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner 104043b429b05989075b60693d57395c99b0ad789f8dChris Lattnerbool JITEmitter::finishFunction(MachineFunction &F) { 1041e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner if (CurBufferPtr == BufferEnd) { 1042e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner // FIXME: Allocate more space, then try again. 1043832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling cerr << "JIT: Ran out of space for generated machine code!\n"; 1044e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner abort(); 1045e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner } 1046e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 1047b92767afd442a8363a8696e54880ee31c5d48c1eJim Laskey emitJumpTableInfo(F.getJumpTableInfo()); 1048b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner 1049a827953c32e420740c281b4a38a056d15b180932Chris Lattner // FnStart is the start of the text, not the start of the constant pool and 1050a827953c32e420740c281b4a38a056d15b180932Chris Lattner // other per-function data. 1051a827953c32e420740c281b4a38a056d15b180932Chris Lattner unsigned char *FnStart = 1052a827953c32e420740c281b4a38a056d15b180932Chris Lattner (unsigned char *)TheJIT->getPointerToGlobalIfAvailable(F.getFunction()); 1053bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner 105419fee415f63ddb78fca703085fe56510be3e058cArgyrios Kyrtzidis // FnEnd is the end of the function's machine code. 105519fee415f63ddb78fca703085fe56510be3e058cArgyrios Kyrtzidis unsigned char *FnEnd = CurBufferPtr; 105619fee415f63ddb78fca703085fe56510be3e058cArgyrios Kyrtzidis 10575be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner if (!Relocations.empty()) { 105850cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman CurFn = F.getFunction(); 1059e884dc2c586bc2f6646ffce89fef5100b412326eChris Lattner NumRelos += Relocations.size(); 1060e884dc2c586bc2f6646ffce89fef5100b412326eChris Lattner 10615be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner // Resolve the relocations to concrete pointers. 10625be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { 10635be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner MachineRelocation &MR = Relocations[i]; 10649200605cd5f6db50be20efb7df926dc5a0d19a4dEvan Cheng void *ResultPtr = 0; 1065ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng if (!MR.letTargetResolve()) { 1066d7398c9b699cae3a109e9808401f7d0b2fc7e686Evan Cheng if (MR.isExternalSymbol()) { 106769f9378675b23135043d93aa58300fed3ec41cbfDan Gohman ResultPtr = TheJIT->getPointerToNamedFunction(MR.getExternalSymbol(), 106869f9378675b23135043d93aa58300fed3ec41cbfDan Gohman false); 1069d7398c9b699cae3a109e9808401f7d0b2fc7e686Evan Cheng DOUT << "JIT: Map \'" << MR.getExternalSymbol() << "\' to [" 1070ca66b08bc6c3cf899459e642a5297df8b9ccdb0dEvan Cheng << ResultPtr << "]\n"; 1071ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng 1072ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng // If the target REALLY wants a stub for this function, emit it now. 1073841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman if (!MR.doesntNeedStub()) { 1074841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman if (!TheJIT->areDlsymStubsEnabled()) { 1075841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman ResultPtr = Resolver.getExternalFunctionStub(ResultPtr); 1076841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman } else { 1077841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman void *&Stub = ExtFnStubs[MR.getExternalSymbol()]; 1078841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman if (!Stub) { 1079841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman Stub = Resolver.getExternalFunctionStub((void *)&Stub); 1080841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman AddStubToCurrentFunction(Stub); 1081841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman } 1082841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman ResultPtr = Stub; 1083841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman } 1084841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman } 1085ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng } else if (MR.isGlobalValue()) { 1086ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng ResultPtr = getPointerToGlobal(MR.getGlobalValue(), 1087ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng BufferBegin+MR.getMachineCodeOffset(), 1088ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng MR.doesntNeedStub()); 10895594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng } else if (MR.isIndirectSymbol()) { 10905594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng ResultPtr = getPointerToGVIndirectSym(MR.getGlobalValue(), 1091be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng BufferBegin+MR.getMachineCodeOffset(), 1092be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng MR.doesntNeedStub()); 1093ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng } else if (MR.isBasicBlock()) { 1094ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock()); 1095ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng } else if (MR.isConstantPoolIndex()) { 1096ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng ResultPtr = (void*)getConstantPoolEntryAddress(MR.getConstantPoolIndex()); 1097ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng } else { 1098ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng assert(MR.isJumpTableIndex()); 1099ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng ResultPtr=(void*)getJumpTableEntryAddress(MR.getJumpTableIndex()); 1100ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng } 110100b16889ab461b7ecef1c91ade101186b7f1fce2Jeff Cohen 1102ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng MR.setResultPointer(ResultPtr); 1103ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng } 110416ec33c6ef630730ad55a4af7242c658e1efb8b3Andrew Lenharth 11056a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth // if we are managing the GOT and the relocation wants an index, 11066a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth // give it one 11078907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner if (MR.isGOTRelative() && MemMgr->isManagingGOT()) { 1108e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner unsigned idx = Resolver.getGOTIndexForAddr(ResultPtr); 11096a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth MR.setGOTIndex(idx); 11108907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner if (((void**)MemMgr->getGOTBase())[idx] != ResultPtr) { 1111eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: GOT was out of date for " << ResultPtr 11128907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] 1113832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << "\n"; 11148907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner ((void**)MemMgr->getGOTBase())[idx] = ResultPtr; 11156a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth } 111616ec33c6ef630730ad55a4af7242c658e1efb8b3Andrew Lenharth } 11175be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner } 11185be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner 111950cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman CurFn = 0; 112043b429b05989075b60693d57395c99b0ad789f8dChris Lattner TheJIT->getJITInfo().relocate(BufferBegin, &Relocations[0], 11218907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner Relocations.size(), MemMgr->getGOTBase()); 11225be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner } 11235be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner 1124d2d5c76753b132c34c71248db2f136b38531bc6dChris Lattner // Update the GOT entry for F to point to the new code. 11258907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner if (MemMgr->isManagingGOT()) { 1126e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner unsigned idx = Resolver.getGOTIndexForAddr((void*)BufferBegin); 11278907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner if (((void**)MemMgr->getGOTBase())[idx] != (void*)BufferBegin) { 1128eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: GOT was out of date for " << (void*)BufferBegin 11298907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] << "\n"; 11308907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner ((void**)MemMgr->getGOTBase())[idx] = (void*)BufferBegin; 11316a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth } 11326a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth } 11336a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth 113419fee415f63ddb78fca703085fe56510be3e058cArgyrios Kyrtzidis // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for 113519fee415f63ddb78fca703085fe56510be3e058cArgyrios Kyrtzidis // global variables that were referenced in the relocations. 113619fee415f63ddb78fca703085fe56510be3e058cArgyrios Kyrtzidis MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr); 11375788d1a169db3346a612a13113348d2709bdd15bEvan Cheng 11385788d1a169db3346a612a13113348d2709bdd15bEvan Cheng if (CurBufferPtr == BufferEnd) { 11395788d1a169db3346a612a13113348d2709bdd15bEvan Cheng // FIXME: Allocate more space, then try again. 11405788d1a169db3346a612a13113348d2709bdd15bEvan Cheng cerr << "JIT: Ran out of space for generated machine code!\n"; 11415788d1a169db3346a612a13113348d2709bdd15bEvan Cheng abort(); 11425788d1a169db3346a612a13113348d2709bdd15bEvan Cheng } 11435788d1a169db3346a612a13113348d2709bdd15bEvan Cheng 1144cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes BufferBegin = CurBufferPtr = 0; 1145cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes NumBytes += FnEnd-FnStart; 1146cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes 114755fc28076fa48723bd170e51638b3b5974ca0fa1Evan Cheng // Invalidate the icache if necessary. 1148bc52cada0933f353d30da7b49af9a641bdb2c57dChris Lattner sys::Memory::InvalidateInstructionCache(FnStart, FnEnd-FnStart); 11498ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 11508ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Add it to the JIT symbol table if the host wants it. 11518ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner AddFunctionToSymbolTable(F.getFunction()->getNameStart(), 11528ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner FnStart, FnEnd-FnStart); 115355fc28076fa48723bd170e51638b3b5974ca0fa1Evan Cheng 1154832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling DOUT << "JIT: Finished CodeGen of [" << (void*)FnStart 1155832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << "] Function: " << F.getFunction()->getName() 1156832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << ": " << (FnEnd-FnStart) << " bytes of text, " 1157832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << Relocations.size() << " relocations\n"; 11585be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner Relocations.clear(); 11591606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng ConstPoolAddresses.clear(); 11608cd4c3e6534a14566bf163301fd45bca34e655c1Anton Korobeynikov 1161bc4707a2554ac04ba006bf70035e7bc7270236a9Evan Cheng // Mark code region readable and executable if it's not so already. 1162cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach MemMgr->setMemoryExecutable(); 1163bc4707a2554ac04ba006bf70035e7bc7270236a9Evan Cheng 1164c5633c235e94f69c6a77e894bcc84d8ba71106f0Chris Lattner#ifndef NDEBUG 1165a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng { 1166e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng if (sys::hasDisassembler()) { 1167e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng DOUT << "JIT: Disassembled code:\n"; 1168eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << sys::disassembleBuffer(FnStart, FnEnd-FnStart, (uintptr_t)FnStart); 1169e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng } else { 1170e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng DOUT << "JIT: Binary code:\n"; 1171a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng DOUT << std::hex; 1172a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng unsigned char* q = FnStart; 1173e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng for (int i = 0; q < FnEnd; q += 4, ++i) { 1174e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng if (i == 4) 1175e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng i = 0; 1176e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng if (i == 0) 1177e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng DOUT << "JIT: " << std::setw(8) << std::setfill('0') 1178e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng << (long)(q - FnStart) << ": "; 1179e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng bool Done = false; 1180e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng for (int j = 3; j >= 0; --j) { 1181e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng if (q + j >= FnEnd) 1182e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng Done = true; 1183e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng else 1184e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng DOUT << std::setw(2) << std::setfill('0') << (unsigned short)q[j]; 1185e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng } 1186e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng if (Done) 1187e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng break; 1188e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng DOUT << ' '; 1189e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng if (i == 3) 11906863fb033a9079e04edc7a568e34098bcf5b9ebeEvan Cheng DOUT << '\n'; 1191a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng } 1192a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng DOUT << std::dec; 11936863fb033a9079e04edc7a568e34098bcf5b9ebeEvan Cheng DOUT<< '\n'; 1194a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng } 1195a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng } 1196c5633c235e94f69c6a77e894bcc84d8ba71106f0Chris Lattner#endif 1197afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray if (ExceptionHandling) { 1198dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray uintptr_t ActualSize = 0; 1199afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray SavedBufferBegin = BufferBegin; 1200afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray SavedBufferEnd = BufferEnd; 1201afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray SavedCurBufferPtr = CurBufferPtr; 1202dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 12035913e6c5dbaff88ac00d5e679382abc72323831aNicolas Geoffray if (MemMgr->NeedsExactSize()) { 12045913e6c5dbaff88ac00d5e679382abc72323831aNicolas Geoffray ActualSize = DE->GetDwarfTableSizeInBytes(F, *this, FnStart, FnEnd); 1205dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray } 1206afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 1207afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(), 1208afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray ActualSize); 1209afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray BufferEnd = BufferBegin+ActualSize; 1210afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray unsigned char* FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd); 12110fdaa0b8f194f0ef7cec0610c50672b89bd7c17aChris Lattner MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr, 12120fdaa0b8f194f0ef7cec0610c50672b89bd7c17aChris Lattner FrameRegister); 1213afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray BufferBegin = SavedBufferBegin; 1214afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray BufferEnd = SavedBufferEnd; 1215afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray CurBufferPtr = SavedCurBufferPtr; 1216afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 1217afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray TheJIT->RegisterTable(FrameRegister); 1218afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray } 1219252ddfbdbc834d1abe80de9c2205afac7918d3eaEvan Cheng 1220252ddfbdbc834d1abe80de9c2205afac7918d3eaEvan Cheng if (MMI) 1221252ddfbdbc834d1abe80de9c2205afac7918d3eaEvan Cheng MMI->EndFunction(); 1222afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 122343b429b05989075b60693d57395c99b0ad789f8dChris Lattner return false; 1224bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner} 1225bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner 122650cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman/// deallocateMemForFunction - Deallocate all memory for the specified 122750cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman/// function body. Also drop any references the function has to stubs. 122850cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begemanvoid JITEmitter::deallocateMemForFunction(Function *F) { 122950cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman MemMgr->deallocateMemForFunction(F); 123050cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 123150cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // If the function did not reference any stubs, return. 123250cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman if (CurFnStubUses.find(F) == CurFnStubUses.end()) 123350cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman return; 123450cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 123550cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // For each referenced stub, erase the reference to this function, and then 123650cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // erase the list of referenced stubs. 123750cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman SmallVectorImpl<void *> &StubList = CurFnStubUses[F]; 123850cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman for (unsigned i = 0, e = StubList.size(); i != e; ++i) { 123950cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman void *Stub = StubList[i]; 1240841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman 1241841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman // If we already invalidated this stub for this function, continue. 1242841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman if (StubFnRefs.count(Stub) == 0) 1243841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman continue; 1244841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman 124550cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman SmallPtrSet<const Function *, 1> &FnRefs = StubFnRefs[Stub]; 124650cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman FnRefs.erase(F); 124750cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 124850cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // If this function was the last reference to the stub, invalidate the stub 124950cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // in the JITResolver. Were there a memory manager deallocateStub routine, 125050cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // we could call that at this point too. 125150cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman if (FnRefs.empty()) { 1252b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman DOUT << "\nJIT: Invalidated Stub at [" << Stub << "]\n"; 1253841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman StubFnRefs.erase(Stub); 1254841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman 1255841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman // Invalidate the stub. If it is a GV stub, update the JIT's global 1256841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman // mapping for that GV to zero, otherwise, search the string map of 1257841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman // external function names to stubs and remove the entry for this stub. 1258b9c6c9bfe410bbea357503872ce662d6838026ceNate Begeman GlobalValue *GV = Resolver.invalidateStub(Stub); 1259841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman if (GV) { 1260841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman TheJIT->updateGlobalMapping(GV, 0); 1261841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman } else { 1262841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman for (StringMapIterator<void*> i = ExtFnStubs.begin(), 1263841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman e = ExtFnStubs.end(); i != e; ++i) { 1264841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman if (i->second == Stub) { 1265841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman ExtFnStubs.erase(i); 1266841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman break; 1267841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman } 1268841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman } 1269841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman } 127050cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman } 127150cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman } 127250cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman CurFnStubUses.erase(F); 127350cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman} 127450cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 127550cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman 12765788d1a169db3346a612a13113348d2709bdd15bEvan Chengvoid* JITEmitter::allocateSpace(uintptr_t Size, unsigned Alignment) { 1277cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes if (BufferBegin) 1278cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes return MachineCodeEmitter::allocateSpace(Size, Alignment); 1279cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes 1280cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes // create a new memory block if there is no active one. 1281cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes // care must be taken so that BufferBegin is invalidated when a 1282cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes // block is trimmed 1283cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes BufferBegin = CurBufferPtr = MemMgr->allocateSpace(Size, Alignment); 1284cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes BufferEnd = BufferBegin+Size; 1285cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes return CurBufferPtr; 1286cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes} 1287cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes 1288166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattnervoid JITEmitter::emitConstantPool(MachineConstantPool *MCP) { 128947c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng if (TheJIT->getJITInfo().hasCustomConstantPool()) 12908fe95356dd487a79145ec07a9f46cd743b4c9bddJim Grosbach return; 129147c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng 1292fa77d43ba1d91ed39f46e11caeb28dcabae9e193Chris Lattner const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants(); 12932c0a6a19ef42f2ad547dbc0693e55e082a21ac8bChris Lattner if (Constants.empty()) return; 12942c0a6a19ef42f2ad547dbc0693e55e082a21ac8bChris Lattner 12951606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng unsigned Size = GetConstantPoolSizeInBytes(MCP, TheJIT->getTargetData()); 12961606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng unsigned Align = MCP->getConstantPoolAlignment(); 129797b8c40d095c4eb5d8e8ff5ac6da567f043bd8baEvan Cheng ConstantPoolBase = allocateSpace(Size, Align); 1298239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner ConstantPool = MCP; 1299f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 1300f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner if (ConstantPoolBase == 0) return; // Buffer overflow. 1301f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 130297b8c40d095c4eb5d8e8ff5ac6da567f043bd8baEvan Cheng DOUT << "JIT: Emitted constant pool at [" << ConstantPoolBase 130397b8c40d095c4eb5d8e8ff5ac6da567f043bd8baEvan Cheng << "] (size: " << Size << ", alignment: " << Align << ")\n"; 130497b8c40d095c4eb5d8e8ff5ac6da567f043bd8baEvan Cheng 1305239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner // Initialize the memory for all of the constant pool entries. 13061606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng unsigned Offset = 0; 13073029f920519e0871a5aad5d7c592281093953733Chris Lattner for (unsigned i = 0, e = Constants.size(); i != e; ++i) { 13081606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng MachineConstantPoolEntry CPE = Constants[i]; 13091606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng unsigned AlignMask = CPE.getAlignment() - 1; 13101606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng Offset = (Offset + AlignMask) & ~AlignMask; 13111606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng 13121606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng uintptr_t CAddr = (uintptr_t)ConstantPoolBase + Offset; 13131606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng ConstPoolAddresses.push_back(CAddr); 13141606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng if (CPE.isMachineConstantPoolEntry()) { 1315cd5731d98b15c9de236bd0dd6c9c57d9bcecbcebEvan Cheng // FIXME: add support to lower machine constant pool values into bytes! 1316832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling cerr << "Initialize memory with machine specific constant pool entry" 1317832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << " has not been implemented!\n"; 1318cd5731d98b15c9de236bd0dd6c9c57d9bcecbcebEvan Cheng abort(); 1319cd5731d98b15c9de236bd0dd6c9c57d9bcecbcebEvan Cheng } 13201606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng TheJIT->InitializeMemory(CPE.Val.ConstVal, (void*)CAddr); 13211606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng DOUT << "JIT: CP" << i << " at [0x" 13221606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng << std::hex << CAddr << std::dec << "]\n"; 13231606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng 13241606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng const Type *Ty = CPE.Val.ConstVal->getType(); 1325777d2306b36816a53bc1ae1244c0dc7d998ae691Duncan Sands Offset += TheJIT->getTargetData()->getTypeAllocSize(Ty); 13261cc08381f1ab57efdf07248fd5e9fd75ef6f0f99Chris Lattner } 13271cc08381f1ab57efdf07248fd5e9fd75ef6f0f99Chris Lattner} 13281cc08381f1ab57efdf07248fd5e9fd75ef6f0f99Chris Lattner 132937efe6764568a3829fee26aba532283131d1a104Nate Begemanvoid JITEmitter::initJumpTableInfo(MachineJumpTableInfo *MJTI) { 133047c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng if (TheJIT->getJITInfo().hasCustomJumpTables()) 133147c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng return; 133247c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng 133337efe6764568a3829fee26aba532283131d1a104Nate Begeman const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 133437efe6764568a3829fee26aba532283131d1a104Nate Begeman if (JT.empty()) return; 133537efe6764568a3829fee26aba532283131d1a104Nate Begeman 1336f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner unsigned NumEntries = 0; 133737efe6764568a3829fee26aba532283131d1a104Nate Begeman for (unsigned i = 0, e = JT.size(); i != e; ++i) 1338f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner NumEntries += JT[i].MBBs.size(); 1339f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 1340f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner unsigned EntrySize = MJTI->getEntrySize(); 1341f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 134237efe6764568a3829fee26aba532283131d1a104Nate Begeman // Just allocate space for all the jump tables now. We will fix up the actual 134337efe6764568a3829fee26aba532283131d1a104Nate Begeman // MBB entries in the tables after we emit the code for each block, since then 134437efe6764568a3829fee26aba532283131d1a104Nate Begeman // we will know the final locations of the MBBs in memory. 134537efe6764568a3829fee26aba532283131d1a104Nate Begeman JumpTable = MJTI; 1346f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner JumpTableBase = allocateSpace(NumEntries * EntrySize, MJTI->getAlignment()); 134737efe6764568a3829fee26aba532283131d1a104Nate Begeman} 134837efe6764568a3829fee26aba532283131d1a104Nate Begeman 1349b92767afd442a8363a8696e54880ee31c5d48c1eJim Laskeyvoid JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { 135047c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng if (TheJIT->getJITInfo().hasCustomJumpTables()) 135147c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng return; 135247c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng 135337efe6764568a3829fee26aba532283131d1a104Nate Begeman const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 1354f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner if (JT.empty() || JumpTableBase == 0) return; 135537efe6764568a3829fee26aba532283131d1a104Nate Begeman 1356b92767afd442a8363a8696e54880ee31c5d48c1eJim Laskey if (TargetMachine::getRelocationModel() == Reloc::PIC_) { 1357acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey assert(MJTI->getEntrySize() == 4 && "Cross JIT'ing?"); 1358acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // For each jump table, place the offset from the beginning of the table 1359acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // to the target address. 1360acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey int *SlotPtr = (int*)JumpTableBase; 1361acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey 1362acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey for (unsigned i = 0, e = JT.size(); i != e; ++i) { 1363acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs; 1364acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // Store the offset of the basic block for this jump table slot in the 1365acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // memory we allocated for the jump table in 'initJumpTableInfo' 13665788d1a169db3346a612a13113348d2709bdd15bEvan Cheng uintptr_t Base = (uintptr_t)SlotPtr; 13672a3e08b5961353fa3faeadf81f481ae9f5463427Evan Cheng for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { 13685788d1a169db3346a612a13113348d2709bdd15bEvan Cheng uintptr_t MBBAddr = getMachineBasicBlockAddress(MBBs[mi]); 13692a3e08b5961353fa3faeadf81f481ae9f5463427Evan Cheng *SlotPtr++ = TheJIT->getJITInfo().getPICJumpTableEntry(MBBAddr, Base); 13702a3e08b5961353fa3faeadf81f481ae9f5463427Evan Cheng } 1371acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey } 1372acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey } else { 1373acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey assert(MJTI->getEntrySize() == sizeof(void*) && "Cross JIT'ing?"); 1374acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey 1375acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // For each jump table, map each target in the jump table to the address of 1376acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // an emitted MachineBasicBlock. 1377acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey intptr_t *SlotPtr = (intptr_t*)JumpTableBase; 1378acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey 1379acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey for (unsigned i = 0, e = JT.size(); i != e; ++i) { 1380acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs; 1381acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // Store the address of the basic block for this jump table slot in the 1382acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // memory we allocated for the jump table in 'initJumpTableInfo' 1383acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) 1384acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey *SlotPtr++ = getMachineBasicBlockAddress(MBBs[mi]); 1385acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey } 138637efe6764568a3829fee26aba532283131d1a104Nate Begeman } 138737efe6764568a3829fee26aba532283131d1a104Nate Begeman} 138837efe6764568a3829fee26aba532283131d1a104Nate Begeman 1389ce4a70bd7608861e104b04265a0c71e5df8ecefeEvan Chengvoid JITEmitter::startGVStub(const GlobalValue* GV, unsigned StubSize, 1390ce4a70bd7608861e104b04265a0c71e5df8ecefeEvan Cheng unsigned Alignment) { 139143b429b05989075b60693d57395c99b0ad789f8dChris Lattner SavedBufferBegin = BufferBegin; 139243b429b05989075b60693d57395c99b0ad789f8dChris Lattner SavedBufferEnd = BufferEnd; 139343b429b05989075b60693d57395c99b0ad789f8dChris Lattner SavedCurBufferPtr = CurBufferPtr; 139443b429b05989075b60693d57395c99b0ad789f8dChris Lattner 1395ce4a70bd7608861e104b04265a0c71e5df8ecefeEvan Cheng BufferBegin = CurBufferPtr = MemMgr->allocateStub(GV, StubSize, Alignment); 139643b429b05989075b60693d57395c99b0ad789f8dChris Lattner BufferEnd = BufferBegin+StubSize+1; 13976125fddb52c3d821a4e4c000cbd210428b0009f6Chris Lattner} 13986125fddb52c3d821a4e4c000cbd210428b0009f6Chris Lattner 1399d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begemanvoid JITEmitter::startGVStub(const GlobalValue* GV, void *Buffer, 1400d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman unsigned StubSize) { 1401d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman SavedBufferBegin = BufferBegin; 1402d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman SavedBufferEnd = BufferEnd; 1403d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman SavedCurBufferPtr = CurBufferPtr; 1404d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 1405d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman BufferBegin = CurBufferPtr = (unsigned char *)Buffer; 1406d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman BufferEnd = BufferBegin+StubSize+1; 1407d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman} 1408d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 1409ce4a70bd7608861e104b04265a0c71e5df8ecefeEvan Chengvoid *JITEmitter::finishGVStub(const GlobalValue* GV) { 141043b429b05989075b60693d57395c99b0ad789f8dChris Lattner NumBytes += getCurrentPCOffset(); 141143b429b05989075b60693d57395c99b0ad789f8dChris Lattner std::swap(SavedBufferBegin, BufferBegin); 141243b429b05989075b60693d57395c99b0ad789f8dChris Lattner BufferEnd = SavedBufferEnd; 141343b429b05989075b60693d57395c99b0ad789f8dChris Lattner CurBufferPtr = SavedCurBufferPtr; 141443b429b05989075b60693d57395c99b0ad789f8dChris Lattner return SavedBufferBegin; 1415bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner} 1416bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner 1417bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner// getConstantPoolEntryAddress - Return the address of the 'ConstantNum' entry 1418bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner// in the constant pool that was last emitted with the 'emitConstantPool' 1419bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner// method. 1420bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner// 14215788d1a169db3346a612a13113348d2709bdd15bEvan Chenguintptr_t JITEmitter::getConstantPoolEntryAddress(unsigned ConstantNum) const { 1422239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner assert(ConstantNum < ConstantPool->getConstants().size() && 14233c94497ec7852eccd68c1bc1663e8ac2a7bb1ab9Misha Brukman "Invalid ConstantPoolIndex!"); 14241606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng return ConstPoolAddresses[ConstantNum]; 1425bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner} 1426bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner 142737efe6764568a3829fee26aba532283131d1a104Nate Begeman// getJumpTableEntryAddress - Return the address of the JumpTable with index 142837efe6764568a3829fee26aba532283131d1a104Nate Begeman// 'Index' in the jumpp table that was last initialized with 'initJumpTableInfo' 142937efe6764568a3829fee26aba532283131d1a104Nate Begeman// 14305788d1a169db3346a612a13113348d2709bdd15bEvan Chenguintptr_t JITEmitter::getJumpTableEntryAddress(unsigned Index) const { 143137efe6764568a3829fee26aba532283131d1a104Nate Begeman const std::vector<MachineJumpTableEntry> &JT = JumpTable->getJumpTables(); 143237efe6764568a3829fee26aba532283131d1a104Nate Begeman assert(Index < JT.size() && "Invalid jump table index!"); 143337efe6764568a3829fee26aba532283131d1a104Nate Begeman 143437efe6764568a3829fee26aba532283131d1a104Nate Begeman unsigned Offset = 0; 143537efe6764568a3829fee26aba532283131d1a104Nate Begeman unsigned EntrySize = JumpTable->getEntrySize(); 143637efe6764568a3829fee26aba532283131d1a104Nate Begeman 143737efe6764568a3829fee26aba532283131d1a104Nate Begeman for (unsigned i = 0; i < Index; ++i) 1438acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey Offset += JT[i].MBBs.size(); 1439acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey 1440acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey Offset *= EntrySize; 144137efe6764568a3829fee26aba532283131d1a104Nate Begeman 14425788d1a169db3346a612a13113348d2709bdd15bEvan Cheng return (uintptr_t)((char *)JumpTableBase + Offset); 144337efe6764568a3829fee26aba532283131d1a104Nate Begeman} 144437efe6764568a3829fee26aba532283131d1a104Nate Begeman 1445e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner//===----------------------------------------------------------------------===// 1446e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner// Public interface to this file 1447e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner//===----------------------------------------------------------------------===// 1448e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 14499f2f142d255bc96f109dd5c6524a485937b1f3a1Chris LattnerMachineCodeEmitter *JIT::createEmitter(JIT &jit, JITMemoryManager *JMM) { 14509f2f142d255bc96f109dd5c6524a485937b1f3a1Chris Lattner return new JITEmitter(jit, JMM); 1451e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner} 1452e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 1453d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman// getPointerToNamedFunction - This function is used as a global wrapper to 14544d326fa9bea5b80147edf14d1521fc41ce315275Chris Lattner// JIT::getPointerToNamedFunction for the purpose of resolving symbols when 1455d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman// bugpoint is debugging the JIT. In that scenario, we are loading an .so and 1456d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman// need to resolve function(s) that are being mis-codegenerated, so we need to 1457d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman// resolve their addresses at runtime, and this is the way to do it. 1458d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukmanextern "C" { 1459d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman void *getPointerToNamedFunction(const char *Name) { 1460fe854034677f59baca1e38075e71f6efca247a03Chris Lattner if (Function *F = TheJIT->FindFunctionNamed(Name)) 14614d326fa9bea5b80147edf14d1521fc41ce315275Chris Lattner return TheJIT->getPointerToFunction(F); 14624d326fa9bea5b80147edf14d1521fc41ce315275Chris Lattner return TheJIT->getPointerToNamedFunction(Name); 1463d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman } 1464d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman} 1465e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 1466e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner// getPointerToFunctionOrStub - If the specified function has been 1467e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner// code-gen'd, return a pointer to the function. If not, compile it, or use 1468e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner// a stub to implement lazy compilation if available. 1469e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner// 1470e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattnervoid *JIT::getPointerToFunctionOrStub(Function *F) { 1471e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner // If we have already code generated the function, just return the address. 1472e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner if (void *Addr = getPointerToGlobalIfAvailable(F)) 1473e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner return Addr; 1474e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 1475e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner // Get a stub if the target supports it. 1476a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng assert(isa<JITEmitter>(MCE) && "Unexpected MCE?"); 1477a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng JITEmitter *JE = cast<JITEmitter>(getCodeEmitter()); 1478e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner return JE->getJITResolver().getFunctionStub(F); 1479e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner} 1480e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 1481d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begemanvoid JIT::updateFunctionStub(Function *F) { 1482d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman // Get the empty stub we generated earlier. 1483d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman assert(isa<JITEmitter>(MCE) && "Unexpected MCE?"); 1484d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman JITEmitter *JE = cast<JITEmitter>(getCodeEmitter()); 1485d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman void *Stub = JE->getJITResolver().getFunctionStub(F); 1486d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 1487d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman // Tell the target jit info to rewrite the stub at the specified address, 1488d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman // rather than creating a new one. 1489d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman void *Addr = getPointerToGlobalIfAvailable(F); 1490d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman getJITInfo().emitFunctionStubAtAddr(F, Addr, Stub, *getCodeEmitter()); 1491d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman} 1492d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 1493d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman/// updateDlsymStubTable - Emit the data necessary to relocate the stubs 1494d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman/// that were emitted during code generation. 1495d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman/// 1496d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begemanvoid JIT::updateDlsymStubTable() { 1497d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman assert(isa<JITEmitter>(MCE) && "Unexpected MCE?"); 1498d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman JITEmitter *JE = cast<JITEmitter>(getCodeEmitter()); 1499d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 1500d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman SmallVector<GlobalValue*, 8> GVs; 1501d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman SmallVector<void*, 8> Ptrs; 1502841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman const StringMap<void *> &ExtFns = JE->getExternalFnStubs(); 1503d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 1504d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman JE->getJITResolver().getRelocatableGVs(GVs, Ptrs); 1505d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 1506841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman unsigned nStubs = GVs.size() + ExtFns.size(); 1507841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman 1508d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman // If there are no relocatable stubs, return. 1509841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman if (nStubs == 0) 1510d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman return; 1511d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 1512d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman // If there are no new relocatable stubs, return. 1513d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman void *CurTable = JE->getMemMgr()->getDlsymTable(); 1514841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman if (CurTable && (*(unsigned *)CurTable == nStubs)) 1515d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman return; 1516d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 1517d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman // Calculate the size of the stub info 1518841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman unsigned offset = 4 + 4 * nStubs + sizeof(intptr_t) * nStubs; 1519d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 1520d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman SmallVector<unsigned, 8> Offsets; 1521d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman for (unsigned i = 0; i != GVs.size(); ++i) { 1522d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman Offsets.push_back(offset); 1523d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman offset += GVs[i]->getName().length() + 1; 1524d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman } 1525841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman for (StringMapConstIterator<void*> i = ExtFns.begin(), e = ExtFns.end(); 1526841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman i != e; ++i) { 1527841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman Offsets.push_back(offset); 1528841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman offset += strlen(i->first()) + 1; 1529841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman } 1530d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 153150cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // Allocate space for the new "stub", which contains the dlsym table. 1532d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman JE->startGVStub(0, offset, 4); 1533d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 1534d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman // Emit the number of records 1535841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman MCE->emitInt32(nStubs); 1536d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 1537d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman // Emit the string offsets 1538841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman for (unsigned i = 0; i != nStubs; ++i) 1539d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman MCE->emitInt32(Offsets[i]); 1540d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 154166941988de6a295649b33f4c2b0f36a094b2244dNate Begeman // Emit the pointers. Verify that they are at least 2-byte aligned, and set 154266941988de6a295649b33f4c2b0f36a094b2244dNate Begeman // the low bit to 0 == GV, 1 == Function, so that the client code doing the 154366941988de6a295649b33f4c2b0f36a094b2244dNate Begeman // relocation can write the relocated pointer at the appropriate place in 154466941988de6a295649b33f4c2b0f36a094b2244dNate Begeman // the stub. 154566941988de6a295649b33f4c2b0f36a094b2244dNate Begeman for (unsigned i = 0; i != GVs.size(); ++i) { 154666941988de6a295649b33f4c2b0f36a094b2244dNate Begeman intptr_t Ptr = (intptr_t)Ptrs[i]; 154766941988de6a295649b33f4c2b0f36a094b2244dNate Begeman assert((Ptr & 1) == 0 && "Stub pointers must be at least 2-byte aligned!"); 154866941988de6a295649b33f4c2b0f36a094b2244dNate Begeman 154966941988de6a295649b33f4c2b0f36a094b2244dNate Begeman if (isa<Function>(GVs[i])) 155066941988de6a295649b33f4c2b0f36a094b2244dNate Begeman Ptr |= (intptr_t)1; 155166941988de6a295649b33f4c2b0f36a094b2244dNate Begeman 1552841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman if (sizeof(Ptr) == 8) 1553841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman MCE->emitInt64(Ptr); 1554841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman else 1555841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman MCE->emitInt32(Ptr); 1556841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman } 1557841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman for (StringMapConstIterator<void*> i = ExtFns.begin(), e = ExtFns.end(); 1558841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman i != e; ++i) { 1559841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman intptr_t Ptr = (intptr_t)i->second | 1; 1560841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman 1561841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman if (sizeof(Ptr) == 8) 156266941988de6a295649b33f4c2b0f36a094b2244dNate Begeman MCE->emitInt64(Ptr); 1563d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman else 156466941988de6a295649b33f4c2b0f36a094b2244dNate Begeman MCE->emitInt32(Ptr); 156566941988de6a295649b33f4c2b0f36a094b2244dNate Begeman } 1566d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 156750cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // Emit the strings. 1568d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman for (unsigned i = 0; i != GVs.size(); ++i) 1569d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman MCE->emitString(GVs[i]->getName()); 1570841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman for (StringMapConstIterator<void*> i = ExtFns.begin(), e = ExtFns.end(); 1571841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman i != e; ++i) 1572841c6a4345082e9a1252cc39bcce7f1423a76dedNate Begeman MCE->emitString(i->first()); 1573d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 157450cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // Tell the JIT memory manager where it is. The JIT Memory Manager will 157550cd6fda9e98f68a9a6e1adf72c38baf614bd305Nate Begeman // deallocate space for the old one, if one existed. 1576d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman JE->getMemMgr()->SetDlsymTable(JE->finishGVStub(0)); 1577d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman} 1578d6b7a242d345fd79a337afd384bb586c5619cfe7Nate Begeman 1579e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner/// freeMachineCodeForFunction - release machine code memory for given Function. 1580e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner/// 1581e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattnervoid JIT::freeMachineCodeForFunction(Function *F) { 1582dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 1583e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner // Delete translation for this from the ExecutionEngine, so it will get 1584e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner // retranslated next time it is used. 15858ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner void *OldPtr = updateGlobalMapping(F, 0); 15868ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 15878ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner if (OldPtr) 15888ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner RemoveFunctionFromSymbolTable(OldPtr); 1589e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 1590e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner // Free the actual memory for the function body and related stuff. 1591a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng assert(isa<JITEmitter>(MCE) && "Unexpected MCE?"); 1592a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng cast<JITEmitter>(MCE)->deallocateMemForFunction(F); 1593e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner} 1594e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 1595