JITEmitter.cpp revision 5788d1a169db3346a612a13113348d2709bdd15b
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" 35fd58e6e2ecebe92804869586d65b27085110f336Anton Korobeynikov#include "llvm/System/Disassembler.h" 36bc52cada0933f353d30da7b49af9a641bdb2c57dChris Lattner#include "llvm/System/Memory.h" 37dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray#include "llvm/Target/TargetInstrInfo.h" 3847c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng#include "llvm/ADT/SmallPtrSet.h" 39551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/ADT/Statistic.h" 40a00269bc3e97d4e53ed196325ef02e6d1f3d70dcAndrew Lenharth#include <algorithm> 41a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng#ifndef NDEBUG 42a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng#include <iomanip> 43a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng#endif 44c19aadee66b744311afe6e420847e80822a765f2Chris Lattnerusing namespace llvm; 45d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 4636343735cb23680c8f8675deafbbf825d46fd868Chris LattnerSTATISTIC(NumBytes, "Number of bytes of machine code compiled"); 4736343735cb23680c8f8675deafbbf825d46fd868Chris LattnerSTATISTIC(NumRelos, "Number of relocations applied"); 4836343735cb23680c8f8675deafbbf825d46fd868Chris Lattnerstatic JIT *TheJIT = 0; 49bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner 50a00269bc3e97d4e53ed196325ef02e6d1f3d70dcAndrew Lenharth 515426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner//===----------------------------------------------------------------------===// 525426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner// JIT lazy compilation code. 535426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner// 545426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattnernamespace { 55ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer class JITResolverState { 56ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer private: 57ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer /// FunctionToStubMap - Keep track of the stub created for a particular 58ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer /// function so that we can reuse them if necessary. 59ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer std::map<Function*, void*> FunctionToStubMap; 60ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer 61ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer /// StubToFunctionMap - Keep track of the function that each stub 62ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer /// corresponds to. 63ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer std::map<void*, Function*> StubToFunctionMap; 6400b16889ab461b7ecef1c91ade101186b7f1fce2Jeff Cohen 655594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng /// GlobalToIndirectSymMap - Keep track of the indirect symbol created for a 66be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng /// particular GlobalVariable so that we can reuse them if necessary. 675594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng std::map<GlobalValue*, void*> GlobalToIndirectSymMap; 68be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 69ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer public: 70ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer std::map<Function*, void*>& getFunctionToStubMap(const MutexGuard& locked) { 71ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer assert(locked.holds(TheJIT->lock)); 72ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer return FunctionToStubMap; 73ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer } 7400b16889ab461b7ecef1c91ade101186b7f1fce2Jeff Cohen 75ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer std::map<void*, Function*>& getStubToFunctionMap(const MutexGuard& locked) { 76ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer assert(locked.holds(TheJIT->lock)); 77ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer return StubToFunctionMap; 78ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer } 79be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 80be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng std::map<GlobalValue*, void*>& 815594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng getGlobalToIndirectSymMap(const MutexGuard& locked) { 82be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng assert(locked.holds(TheJIT->lock)); 835594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng return GlobalToIndirectSymMap; 84be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng } 85ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer }; 8600b16889ab461b7ecef1c91ade101186b7f1fce2Jeff Cohen 875426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// JITResolver - Keep track of, and resolve, call sites for functions that 885426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// have not yet been compiled. 895426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner class JITResolver { 905e225588530f641d6627becadffdd7d285bfcdbaChris Lattner /// LazyResolverFn - The target lazy resolver function that we actually 915e225588530f641d6627becadffdd7d285bfcdbaChris Lattner /// rewrite instructions to use. 925e225588530f641d6627becadffdd7d285bfcdbaChris Lattner TargetJITInfo::LazyResolverFn LazyResolverFn; 935e225588530f641d6627becadffdd7d285bfcdbaChris Lattner 94ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer JITResolverState state; 955426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 96d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner /// ExternalFnToStubMap - This is the equivalent of FunctionToStubMap for 97d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner /// external functions. 98d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner std::map<void*, void*> ExternalFnToStubMap; 996a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth 1006a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth //map addresses to indexes in the GOT 1016a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth std::map<void*, unsigned> revGOTMap; 1026a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth unsigned nextGOTIndex; 1036a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth 104e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner static JITResolver *TheJITResolver; 1055426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner public: 106950a4c40b823cd4f09dc71be635229246dfd6cacDan Gohman explicit JITResolver(JIT &jit) : nextGOTIndex(0) { 107e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner TheJIT = &jit; 108e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner 109e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner LazyResolverFn = jit.getJITInfo().getLazyResolverFunction(JITCompilerFn); 110e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner assert(TheJITResolver == 0 && "Multiple JIT resolvers?"); 111e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner TheJITResolver = this; 112e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner } 113e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner 114e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner ~JITResolver() { 115e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner TheJITResolver = 0; 1165e225588530f641d6627becadffdd7d285bfcdbaChris Lattner } 1175426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 118704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng /// getFunctionStubIfAvailable - This returns a pointer to a function stub 119704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng /// if it has already been created. 120704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng void *getFunctionStubIfAvailable(Function *F); 121704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng 1225426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// getFunctionStub - This returns a pointer to a function stub, creating 1235426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// one on demand as needed. 1245426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner void *getFunctionStub(Function *F); 1255426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 126d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner /// getExternalFunctionStub - Return a stub for the function at the 127d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner /// specified address, created lazily on demand. 128d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner void *getExternalFunctionStub(void *FnAddr); 129d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner 1305594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng /// getGlobalValueIndirectSym - Return an indirect symbol containing the 131c96a8e7df1ffeebc5fb876f5eef380e8547ce14fEvan Cheng /// specified GV address. 1325594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng void *getGlobalValueIndirectSym(GlobalValue *V, void *GVAddress); 133be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 1345e225588530f641d6627becadffdd7d285bfcdbaChris Lattner /// AddCallbackAtLocation - If the target is capable of rewriting an 1355e225588530f641d6627becadffdd7d285bfcdbaChris Lattner /// instruction without the use of a stub, record the location of the use so 1365e225588530f641d6627becadffdd7d285bfcdbaChris Lattner /// we know which function is being used at the location. 1375e225588530f641d6627becadffdd7d285bfcdbaChris Lattner void *AddCallbackAtLocation(Function *F, void *Location) { 138ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer MutexGuard locked(TheJIT->lock); 1395e225588530f641d6627becadffdd7d285bfcdbaChris Lattner /// Get the target-specific JIT resolver function. 140ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer state.getStubToFunctionMap(locked)[Location] = F; 141870286aa33290c00e55ba479a60251c79f3a7911Chris Lattner return (void*)(intptr_t)LazyResolverFn; 1425e225588530f641d6627becadffdd7d285bfcdbaChris Lattner } 1435e225588530f641d6627becadffdd7d285bfcdbaChris Lattner 1446a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth /// getGOTIndexForAddress - Return a new or existing index in the GOT for 1458907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner /// an address. This function only manages slots, it does not manage the 1466a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth /// contents of the slots or the memory associated with the GOT. 1478907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner unsigned getGOTIndexForAddr(void *addr); 1486a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth 1495426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// JITCompilerFn - This function is called to resolve a stub to a compiled 1505426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// address. If the LLVM Function corresponding to the stub has not yet 1515426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// been compiled, this function compiles it first. 1525426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner static void *JITCompilerFn(void *Stub); 1535426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner }; 1545426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner} 1555426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 156e748401b180d7041738e14d3896ac61ca4bdfcbaChris LattnerJITResolver *JITResolver::TheJITResolver = 0; 1575426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 158704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng/// getFunctionStubIfAvailable - This returns a pointer to a function stub 159704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng/// if it has already been created. 160704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Chengvoid *JITResolver::getFunctionStubIfAvailable(Function *F) { 161704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng MutexGuard locked(TheJIT->lock); 162704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng 163704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng // If we already have a stub for this function, recycle it. 164704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng void *&Stub = state.getFunctionToStubMap(locked)[F]; 165704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng return Stub; 166704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng} 167704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng 1685426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner/// getFunctionStub - This returns a pointer to a function stub, creating 1695426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner/// one on demand as needed. 1705426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattnervoid *JITResolver::getFunctionStub(Function *F) { 171ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer MutexGuard locked(TheJIT->lock); 172ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer 1735426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // If we already have a stub for this function, recycle it. 174ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer void *&Stub = state.getFunctionToStubMap(locked)[F]; 1755426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner if (Stub) return Stub; 1765426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 177b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner // Call the lazy resolver function unless we already KNOW it is an external 178b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner // function, in which case we just skip the lazy resolution step. 179870286aa33290c00e55ba479a60251c79f3a7911Chris Lattner void *Actual = (void*)(intptr_t)LazyResolverFn; 180a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greif if (F->isDeclaration() && !F->hasNotBeenReadFromBitcode()) 181b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner Actual = TheJIT->getPointerToFunction(F); 182f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman 1835426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // Otherwise, codegen a new stub. For now, the stub will call the lazy 1845426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // resolver function. 18551cc3c13eac78da242f0518fc42580e48dd5304fNicolas Geoffray Stub = TheJIT->getJITInfo().emitFunctionStub(F, Actual, 186e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner *TheJIT->getCodeEmitter()); 187b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner 188870286aa33290c00e55ba479a60251c79f3a7911Chris Lattner if (Actual != (void*)(intptr_t)LazyResolverFn) { 189b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner // If we are getting the stub for an external function, we really want the 190b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner // address of the stub in the GlobalAddressMap for the JIT, not the address 191b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner // of the external function. 192b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner TheJIT->updateGlobalMapping(F, Stub); 193b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner } 1945426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 195832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling DOUT << "JIT: Stub emitted at [" << Stub << "] for function '" 196832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << F->getName() << "'\n"; 197cb47941556800369216c062dcee8dcab7cd39ee9Chris Lattner 1985426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // Finally, keep track of the stub-to-Function mapping so that the 1995426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // JITCompilerFn knows which function to compile! 200ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer state.getStubToFunctionMap(locked)[Stub] = F; 2015426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner return Stub; 2025426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner} 2035426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 2045594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng/// getGlobalValueIndirectSym - Return a lazy pointer containing the specified 205be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng/// GV address. 2065594f120b8880f7c514b0376c4adac1267a0b2b6Evan Chengvoid *JITResolver::getGlobalValueIndirectSym(GlobalValue *GV, void *GVAddress) { 207be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng MutexGuard locked(TheJIT->lock); 208be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 209be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng // If we already have a stub for this global variable, recycle it. 2105594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng void *&IndirectSym = state.getGlobalToIndirectSymMap(locked)[GV]; 2115594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng if (IndirectSym) return IndirectSym; 212be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 213e4d783d584d22d7fcb4cba2a24e0f45f62ed8153Evan Cheng // Otherwise, codegen a new indirect symbol. 2145594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng IndirectSym = TheJIT->getJITInfo().emitGlobalValueIndirectSym(GV, GVAddress, 215c96a8e7df1ffeebc5fb876f5eef380e8547ce14fEvan Cheng *TheJIT->getCodeEmitter()); 216be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 2175594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng DOUT << "JIT: Indirect symbol emitted at [" << IndirectSym << "] for GV '" 218be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng << GV->getName() << "'\n"; 219be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 2205594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng return IndirectSym; 221be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng} 222be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 223d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner/// getExternalFunctionStub - Return a stub for the function at the 224d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner/// specified address, created lazily on demand. 225d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattnervoid *JITResolver::getExternalFunctionStub(void *FnAddr) { 226d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner // If we already have a stub for this function, recycle it. 227d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner void *&Stub = ExternalFnToStubMap[FnAddr]; 228d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner if (Stub) return Stub; 229d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner 23051cc3c13eac78da242f0518fc42580e48dd5304fNicolas Geoffray Stub = TheJIT->getJITInfo().emitFunctionStub(0, FnAddr, 231e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner *TheJIT->getCodeEmitter()); 23255fc28076fa48723bd170e51638b3b5974ca0fa1Evan Cheng 233832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling DOUT << "JIT: Stub emitted at [" << Stub 234832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << "] for external function at '" << FnAddr << "'\n"; 235d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner return Stub; 236d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner} 237d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner 2386a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharthunsigned JITResolver::getGOTIndexForAddr(void* addr) { 2396a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth unsigned idx = revGOTMap[addr]; 2406a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth if (!idx) { 2416a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth idx = ++nextGOTIndex; 2426a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth revGOTMap[addr] = idx; 243366cf29ca537057341ecbad03ab8f9bc52f731e7Evan Cheng DOUT << "JIT: Adding GOT entry " << idx << " for addr [" << addr << "]\n"; 2446a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth } 2456a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth return idx; 2466a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth} 247d91ff7cd3b08cfe30b731799da8358dd9f90558cChris Lattner 2485426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner/// JITCompilerFn - This function is called when a lazy compilation stub has 2495426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner/// been entered. It looks up which function this stub corresponds to, compiles 2505426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner/// it if necessary, then returns the resultant function pointer. 2515426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattnervoid *JITResolver::JITCompilerFn(void *Stub) { 252e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner JITResolver &JR = *TheJITResolver; 253dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray 254dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray Function* F = 0; 255dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray void* ActualPtr = 0; 256dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray 257dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray { 258dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray // Only lock for getting the Function. The call getPointerToFunction made 259dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray // in this function might trigger function materializing, which requires 260dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray // JIT lock to be unlocked. 261dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray MutexGuard locked(TheJIT->lock); 262dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray 263dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray // The address given to us for the stub may not be exactly right, it might be 264dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray // a little bit after the stub. As such, use upper_bound to find it. 265dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray std::map<void*, Function*>::iterator I = 266dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray JR.state.getStubToFunctionMap(locked).upper_bound(Stub); 267dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray assert(I != JR.state.getStubToFunctionMap(locked).begin() && 268dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray "This is not a known stub!"); 269dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray F = (--I)->second; 270dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray ActualPtr = I->first; 271dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray } 2725426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 2739da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // If we have already code generated the function, just return the address. 2749da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng void *Result = TheJIT->getPointerToGlobalIfAvailable(F); 2759da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng 2769da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng if (!Result) { 2779da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // Otherwise we don't have it, do lazy compilation now. 2789da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng 2799da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // If lazy compilation is disabled, emit a useful error message and abort. 2809da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng if (TheJIT->isLazyCompilationDisabled()) { 2819da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng cerr << "LLVM JIT requested to do lazy compilation of function '" 2829da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng << F->getName() << "' when lazy compiles are disabled!\n"; 2839da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng abort(); 2849da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng } 2859cab56d59e2ed6af5fb5137a6e50d4bf915eaccfChris Lattner 2869da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // We might like to remove the stub from the StubToFunction map. 2879da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // We can't do that! Multiple threads could be stuck, waiting to acquire the 2889da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // lock above. As soon as the 1st function finishes compiling the function, 2899da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // the next one will be released, and needs to be able to find the function 2909da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng // it needs to call. 2919da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng //JR.state.getStubToFunctionMap(locked).erase(I); 2929da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng 2939da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng DOUT << "JIT: Lazily resolving function '" << F->getName() 2949da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng << "' In stub ptr = " << Stub << " actual ptr = " 295dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray << ActualPtr << "\n"; 2969da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng 2979da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng Result = TheJIT->getPointerToFunction(F); 2989da60f92d916be01c23b8a9a0eeed448523a7c9bEvan Cheng } 299dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray 300dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray // Reacquire the lock to erase the stub in the map. 301dcb31e179000193c65b3f09b7138ef273dc3ce63Nicolas Geoffray MutexGuard locked(TheJIT->lock); 3025426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 3035426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // We don't need to reuse this stub in the future, as F is now compiled. 304ee448630bdf7eb6037fe2c50518d32010c433ca3Reid Spencer JR.state.getFunctionToStubMap(locked).erase(F); 3055426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 3065426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // FIXME: We could rewrite all references to this stub if we knew them. 3076a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth 308d29b6aa608d69f19b57ebd2ae630b040b1c4951dJeff Cohen // What we will do is set the compiled function address to map to the 309d29b6aa608d69f19b57ebd2ae630b040b1c4951dJeff Cohen // same GOT entry as the stub so that later clients may update the GOT 3106a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth // if they see it still using the stub address. 3116a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth // Note: this is done so the Resolver doesn't have to manage GOT memory 3126a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth // Do this without allocating map space if the target isn't using a GOT 3136a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth if(JR.revGOTMap.find(Stub) != JR.revGOTMap.end()) 3146a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth JR.revGOTMap[Result] = JR.revGOTMap[Stub]; 3156a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth 3165426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner return Result; 3175426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner} 3185426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 3198ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner//===----------------------------------------------------------------------===// 3208ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// Function Index Support 3218ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 3228ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// On MacOS we generate an index of currently JIT'd functions so that 3238ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// performance tools can determine a symbol name and accurate code range for a 3248ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// PC value. Because performance tools are generally asynchronous, the code 3258ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// below is written with the hope that it could be interrupted at any time and 3268ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// have useful answers. However, we don't go crazy with atomic operations, we 3278ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner// just do a "reasonable effort". 3288ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#ifdef __APPLE__ 329bdb6ca178cfbe2490a058deabce7847a05f55db7Evan Cheng#define ENABLE_JIT_SYMBOL_TABLE 0 3308ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#endif 3318ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 3328ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner/// JitSymbolEntry - Each function that is JIT compiled results in one of these 3338ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner/// being added to an array of symbols. This indicates the name of the function 3348ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner/// as well as the address range it occupies. This allows the client to map 3358ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner/// from a PC value to the name of the function. 3368ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattnerstruct JitSymbolEntry { 3378ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner const char *FnName; // FnName - a strdup'd string. 3388ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner void *FnStart; 3398ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner intptr_t FnSize; 3408ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner}; 3418ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 3428ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 3438ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattnerstruct JitSymbolTable { 3448ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// NextPtr - This forms a linked list of JitSymbolTable entries. This 3458ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// pointer is not used right now, but might be used in the future. Consider 3468ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// it reserved for future use. 3478ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolTable *NextPtr; 3488ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 3498ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// Symbols - This is an array of JitSymbolEntry entries. Only the first 3508ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// 'NumSymbols' symbols are valid. 3518ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolEntry *Symbols; 3528ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 3538ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// NumSymbols - This indicates the number entries in the Symbols array that 3548ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// are valid. 3558ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner unsigned NumSymbols; 3568ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 3578ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// NumAllocated - This indicates the amount of space we have in the Symbols 3588ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner /// array. This is a private field that should not be read by external tools. 3598ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner unsigned NumAllocated; 3608ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner}; 3618ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 3628ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#if ENABLE_JIT_SYMBOL_TABLE 3638ac66c122b099bc3eab858bfc18f3cb342efc818Chris LattnerJitSymbolTable *__jitSymbolTable; 3648ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#endif 3658ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 3668ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattnerstatic void AddFunctionToSymbolTable(const char *FnName, 3678ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner void *FnStart, intptr_t FnSize) { 3688ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner assert(FnName != 0 && FnStart != 0 && "Bad symbol to add"); 3698ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolTable **SymTabPtrPtr = 0; 3708ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#if !ENABLE_JIT_SYMBOL_TABLE 3718ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner return; 3728ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#else 3738ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner SymTabPtrPtr = &__jitSymbolTable; 3748ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#endif 3758ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 3768ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // If this is the first entry in the symbol table, add the JitSymbolTable 3778ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // index. 3788ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner if (*SymTabPtrPtr == 0) { 3798ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolTable *New = new JitSymbolTable(); 3808ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner New->NextPtr = 0; 3818ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner New->Symbols = 0; 3828ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner New->NumSymbols = 0; 3838ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner New->NumAllocated = 0; 3848ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner *SymTabPtrPtr = New; 3858ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner } 3868ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 3878ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolTable *SymTabPtr = *SymTabPtrPtr; 3888ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 3898ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // If we have space in the table, reallocate the table. 3908ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner if (SymTabPtr->NumSymbols >= SymTabPtr->NumAllocated) { 3918ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // If we don't have space, reallocate the table. 3923b374489041ac28153c84194dda45e182d8939fcChris Lattner unsigned NewSize = std::max(64U, SymTabPtr->NumAllocated*2); 3938ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolEntry *NewSymbols = new JitSymbolEntry[NewSize]; 3948ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolEntry *OldSymbols = SymTabPtr->Symbols; 3958ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 3968ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Copy the old entries over. 3978ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner memcpy(NewSymbols, OldSymbols, 3983b374489041ac28153c84194dda45e182d8939fcChris Lattner SymTabPtr->NumSymbols*sizeof(OldSymbols[0])); 3998ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4008ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Swap the new symbols in, delete the old ones. 4018ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner SymTabPtr->Symbols = NewSymbols; 4023b374489041ac28153c84194dda45e182d8939fcChris Lattner SymTabPtr->NumAllocated = NewSize; 4038ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner delete [] OldSymbols; 4048ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner } 4058ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4068ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Otherwise, we have enough space, just tack it onto the end of the array. 4078ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolEntry &Entry = SymTabPtr->Symbols[SymTabPtr->NumSymbols]; 4088ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner Entry.FnName = strdup(FnName); 4098ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner Entry.FnStart = FnStart; 4108ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner Entry.FnSize = FnSize; 4118ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner ++SymTabPtr->NumSymbols; 4128ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner} 4138ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4148ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattnerstatic void RemoveFunctionFromSymbolTable(void *FnStart) { 4158ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner assert(FnStart && "Invalid function pointer"); 4168ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolTable **SymTabPtrPtr = 0; 4178ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#if !ENABLE_JIT_SYMBOL_TABLE 4188ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner return; 4198ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#else 4208ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner SymTabPtrPtr = &__jitSymbolTable; 4218ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner#endif 4228ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4238ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolTable *SymTabPtr = *SymTabPtrPtr; 4248ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner JitSymbolEntry *Symbols = SymTabPtr->Symbols; 4258ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4268ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Scan the table to find its index. The table is not sorted, so do a linear 4278ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // scan. 4288ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner unsigned Index; 4298ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner for (Index = 0; Symbols[Index].FnStart != FnStart; ++Index) 4308ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner assert(Index != SymTabPtr->NumSymbols && "Didn't find function!"); 4318ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4328ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Once we have an index, we know to nuke this entry, overwrite it with the 4338ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // entry at the end of the array, making the last entry redundant. 4348ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner const char *OldName = Symbols[Index].FnName; 4358ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner Symbols[Index] = Symbols[SymTabPtr->NumSymbols-1]; 4368ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner free((void*)OldName); 4378ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4388ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Drop the number of symbols in the table. 4398ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner --SymTabPtr->NumSymbols; 4408ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4418ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Finally, if we deleted the final symbol, deallocate the table itself. 442f44085a86a3f3cb743fb8822108d8360dd094539Nate Begeman if (SymTabPtr->NumSymbols != 0) 4438ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner return; 4448ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 4458ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner *SymTabPtrPtr = 0; 4468ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner delete [] Symbols; 4478ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner delete SymTabPtr; 4488ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner} 4495426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 4505426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner//===----------------------------------------------------------------------===// 451166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattner// JITEmitter code. 4525426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner// 453688506de24f04682f9d8563a7d20ab15ab85340bChris Lattnernamespace { 454166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattner /// JITEmitter - The JIT implementation of the MachineCodeEmitter, which is 455166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattner /// used to output functions to memory for execution. 456166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattner class JITEmitter : public MachineCodeEmitter { 4578907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner JITMemoryManager *MemMgr; 458688506de24f04682f9d8563a7d20ab15ab85340bChris Lattner 4596125fddb52c3d821a4e4c000cbd210428b0009f6Chris Lattner // When outputting a function stub in the context of some other function, we 46043b429b05989075b60693d57395c99b0ad789f8dChris Lattner // save BufferBegin/BufferEnd/CurBufferPtr here. 46143b429b05989075b60693d57395c99b0ad789f8dChris Lattner unsigned char *SavedBufferBegin, *SavedBufferEnd, *SavedCurBufferPtr; 462bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner 4635be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner /// Relocations - These are the relocations that the function needs, as 4645be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner /// emitted. 4655be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner std::vector<MachineRelocation> Relocations; 466b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner 467b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner /// MBBLocations - This vector is a mapping from MBB ID's to their address. 468b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner /// It is filled in by the StartMachineBasicBlock callback and queried by 469b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner /// the getMachineBasicBlockAddress callback. 4705788d1a169db3346a612a13113348d2709bdd15bEvan Cheng std::vector<uintptr_t> MBBLocations; 47116ec33c6ef630730ad55a4af7242c658e1efb8b3Andrew Lenharth 472239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner /// ConstantPool - The constant pool for the current function. 473239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner /// 474239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner MachineConstantPool *ConstantPool; 475239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner 476239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner /// ConstantPoolBase - A pointer to the first entry in the constant pool. 477239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner /// 478239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner void *ConstantPoolBase; 47937efe6764568a3829fee26aba532283131d1a104Nate Begeman 480019f851ab26511c089e41b61901f743e75f90714Nate Begeman /// JumpTable - The jump tables for the current function. 48137efe6764568a3829fee26aba532283131d1a104Nate Begeman /// 48237efe6764568a3829fee26aba532283131d1a104Nate Begeman MachineJumpTableInfo *JumpTable; 48337efe6764568a3829fee26aba532283131d1a104Nate Begeman 48437efe6764568a3829fee26aba532283131d1a104Nate Begeman /// JumpTableBase - A pointer to the first entry in the jump table. 48537efe6764568a3829fee26aba532283131d1a104Nate Begeman /// 48637efe6764568a3829fee26aba532283131d1a104Nate Begeman void *JumpTableBase; 4872a3e08b5961353fa3faeadf81f481ae9f5463427Evan Cheng 488e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner /// Resolver - This contains info about the currently resolved functions. 489e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner JITResolver Resolver; 490afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 491afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray /// DE - The dwarf emitter for the jit. 492afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray JITDwarfEmitter *DE; 493afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 494afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray /// LabelLocations - This vector is a mapping from Label ID's to their 495afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray /// address. 4965788d1a169db3346a612a13113348d2709bdd15bEvan Cheng std::vector<uintptr_t> LabelLocations; 497afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 498afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray /// MMI - Machine module info for exception informations 499afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray MachineModuleInfo* MMI; 500afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 501dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // GVSet - a set to keep track of which globals have been seen 50247c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng SmallPtrSet<const GlobalVariable*, 8> GVSet; 503dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 504e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner public: 5059f2f142d255bc96f109dd5c6524a485937b1f3a1Chris Lattner JITEmitter(JIT &jit, JITMemoryManager *JMM) : Resolver(jit) { 5069f2f142d255bc96f109dd5c6524a485937b1f3a1Chris Lattner MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager(); 5078907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner if (jit.getJITInfo().needsGOT()) { 5088907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner MemMgr->AllocateGOT(); 5098907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner DOUT << "JIT is managing a GOT\n"; 5108907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner } 511afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 512afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray if (ExceptionHandling) DE = new JITDwarfEmitter(jit); 5138907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner } 5148907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner ~JITEmitter() { 5158907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner delete MemMgr; 516afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray if (ExceptionHandling) delete DE; 51716ec33c6ef630730ad55a4af7242c658e1efb8b3Andrew Lenharth } 518a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng 519a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng /// classof - Methods for support type inquiry through isa, cast, and 520a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng /// dyn_cast: 521a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng /// 522a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng static inline bool classof(const JITEmitter*) { return true; } 523a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng static inline bool classof(const MachineCodeEmitter*) { return true; } 524e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner 525e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner JITResolver &getJITResolver() { return Resolver; } 526bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner 527bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner virtual void startFunction(MachineFunction &F); 52843b429b05989075b60693d57395c99b0ad789f8dChris Lattner virtual bool finishFunction(MachineFunction &F); 529f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 530f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner void emitConstantPool(MachineConstantPool *MCP); 531f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner void initJumpTableInfo(MachineJumpTableInfo *MJTI); 532b92767afd442a8363a8696e54880ee31c5d48c1eJim Laskey void emitJumpTableInfo(MachineJumpTableInfo *MJTI); 533f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 534ce4a70bd7608861e104b04265a0c71e5df8ecefeEvan Cheng virtual void startGVStub(const GlobalValue* GV, unsigned StubSize, 53551cc3c13eac78da242f0518fc42580e48dd5304fNicolas Geoffray unsigned Alignment = 1); 536ce4a70bd7608861e104b04265a0c71e5df8ecefeEvan Cheng virtual void* finishGVStub(const GlobalValue *GV); 537bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner 538cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes /// allocateSpace - Reserves space in the current block if any, or 539cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes /// allocate a new one of the given size. 5405788d1a169db3346a612a13113348d2709bdd15bEvan Cheng virtual void *allocateSpace(uintptr_t Size, unsigned Alignment); 541cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes 5425be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner virtual void addRelocation(const MachineRelocation &MR) { 5435be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner Relocations.push_back(MR); 5445be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner } 545b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner 546b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { 547b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner if (MBBLocations.size() <= (unsigned)MBB->getNumber()) 548b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner MBBLocations.resize((MBB->getNumber()+1)*2); 549b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner MBBLocations[MBB->getNumber()] = getCurrentPCValue(); 550366cf29ca537057341ecbad03ab8f9bc52f731e7Evan Cheng DOUT << "JIT: Emitting BB" << MBB->getNumber() << " at [" 551366cf29ca537057341ecbad03ab8f9bc52f731e7Evan Cheng << (void*) getCurrentPCValue() << "]\n"; 552b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner } 553b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner 5545788d1a169db3346a612a13113348d2709bdd15bEvan Cheng virtual uintptr_t getConstantPoolEntryAddress(unsigned Entry) const; 5555788d1a169db3346a612a13113348d2709bdd15bEvan Cheng virtual uintptr_t getJumpTableEntryAddress(unsigned Entry) const; 5562a3e08b5961353fa3faeadf81f481ae9f5463427Evan Cheng 5575788d1a169db3346a612a13113348d2709bdd15bEvan Cheng virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { 558b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner assert(MBBLocations.size() > (unsigned)MBB->getNumber() && 559b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner MBBLocations[MBB->getNumber()] && "MBB not emitted!"); 560b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner return MBBLocations[MBB->getNumber()]; 561b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner } 5625be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner 563e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner /// deallocateMemForFunction - Deallocate all memory for the specified 564e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner /// function body. 565e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner void deallocateMemForFunction(Function *F) { 5668907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner MemMgr->deallocateMemForFunction(F); 567e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner } 568afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 569afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray virtual void emitLabel(uint64_t LabelID) { 570afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray if (LabelLocations.size() <= LabelID) 571afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray LabelLocations.resize((LabelID+1)*2); 572afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray LabelLocations[LabelID] = getCurrentPCValue(); 573afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray } 574afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 5755788d1a169db3346a612a13113348d2709bdd15bEvan Cheng virtual uintptr_t getLabelAddress(uint64_t LabelID) const { 576afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray assert(LabelLocations.size() > (unsigned)LabelID && 577afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray LabelLocations[LabelID] && "Label not emitted!"); 578afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray return LabelLocations[LabelID]; 579afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray } 580afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 581afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray virtual void setModuleInfo(MachineModuleInfo* Info) { 582afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray MMI = Info; 583afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray if (ExceptionHandling) DE->setModuleInfo(Info); 584afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray } 585afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 586cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach void setMemoryExecutable(void) { 587cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach MemMgr->setMemoryExecutable(); 588cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach } 589cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach 5905426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner private: 5915e225588530f641d6627becadffdd7d285bfcdbaChris Lattner void *getPointerToGlobal(GlobalValue *GV, void *Reference, bool NoNeedStub); 5925594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng void *getPointerToGVIndirectSym(GlobalValue *V, void *Reference, 593e4d783d584d22d7fcb4cba2a24e0f45f62ed8153Evan Cheng bool NoNeedStub); 594dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned addSizeOfGlobal(const GlobalVariable *GV, unsigned Size); 595dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned addSizeOfGlobalsInConstantVal(const Constant *C, unsigned Size); 596dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned addSizeOfGlobalsInInitializer(const Constant *Init, unsigned Size); 597dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned GetSizeOfGlobalsInBytes(MachineFunction &MF); 598bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner }; 599bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner} 600bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner 601166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattnervoid *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference, 602166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattner bool DoesntNeedStub) { 6035426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) { 6045426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// FIXME: If we straightened things out, this could actually emit the 6055426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner /// global immediately instead of queuing it for codegen later! 6065426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner return TheJIT->getOrEmitGlobalVariable(GV); 6075426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner } 60818e045983757a7d2bae482d2abe444a5bb3ed134Chris Lattner if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) 60919e861a4ffb896f16a691d5ac869e894df3cd464Anton Korobeynikov return TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false)); 6105426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 6115426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // If we have already compiled the function, return a pointer to its body. 6125426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner Function *F = cast<Function>(V); 613704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng void *ResultPtr; 614369e02da1b0f7a183c7d15a5d87a1a2c3db5f45aEvan Cheng if (!DoesntNeedStub && !TheJIT->isLazyCompilationDisabled()) 615704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng // Return the function stub if it's already created. 616704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng ResultPtr = Resolver.getFunctionStubIfAvailable(F); 617704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng else 618704bff9e6cf0070924eb11d9e81e5ba6962ae4efEvan Cheng ResultPtr = TheJIT->getPointerToGlobalIfAvailable(F); 6195426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner if (ResultPtr) return ResultPtr; 6205426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 621a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greif if (F->isDeclaration() && !F->hasNotBeenReadFromBitcode()) { 6225426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // If this is an external function pointer, we can force the JIT to 6235426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // 'compile' it, which really just adds it to the map. 624b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner if (DoesntNeedStub) 625b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner return TheJIT->getPointerToFunction(F); 626b43dbdcb20245db6712b2a5a8b52e9b5d8220fedChris Lattner 627e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner return Resolver.getFunctionStub(F); 6285426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner } 6295426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 6305e225588530f641d6627becadffdd7d285bfcdbaChris Lattner // Okay, the function has not been compiled yet, if the target callback 6315e225588530f641d6627becadffdd7d285bfcdbaChris Lattner // mechanism is capable of rewriting the instruction directly, prefer to do 6325e225588530f641d6627becadffdd7d285bfcdbaChris Lattner // that instead of emitting a stub. 6335e225588530f641d6627becadffdd7d285bfcdbaChris Lattner if (DoesntNeedStub) 634e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner return Resolver.AddCallbackAtLocation(F, Reference); 6355e225588530f641d6627becadffdd7d285bfcdbaChris Lattner 6365426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner // Otherwise, we have to emit a lazy resolving stub. 637e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner return Resolver.getFunctionStub(F); 6385426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner} 6395426652c25a5d960bdd3272aa3b90fc8203a5a66Chris Lattner 6405594f120b8880f7c514b0376c4adac1267a0b2b6Evan Chengvoid *JITEmitter::getPointerToGVIndirectSym(GlobalValue *V, void *Reference, 641e4d783d584d22d7fcb4cba2a24e0f45f62ed8153Evan Cheng bool NoNeedStub) { 642be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng // Make sure GV is emitted first. 643be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng // FIXME: For now, if the GV is an external function we force the JIT to 6445594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng // compile it so the indirect symbol will contain the fully resolved address. 645be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng void *GVAddress = getPointerToGlobal(V, Reference, true); 6465594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng return Resolver.getGlobalValueIndirectSym(V, GVAddress); 647be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng} 648be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 649dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffraystatic unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP) { 650dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants(); 651dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray if (Constants.empty()) return 0; 652dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 653dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray MachineConstantPoolEntry CPE = Constants.back(); 654dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray unsigned Size = CPE.Offset; 655dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray const Type *Ty = CPE.isMachineConstantPoolEntry() 656dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray ? CPE.Val.MachineCPVal->getType() : CPE.Val.ConstVal->getType(); 657dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray Size += TheJIT->getTargetData()->getABITypeSize(Ty); 658dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray return Size; 659dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray} 660dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 661dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffraystatic unsigned GetJumpTableSizeInBytes(MachineJumpTableInfo *MJTI) { 662dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 663dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray if (JT.empty()) return 0; 664dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 665dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray unsigned NumEntries = 0; 666dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray for (unsigned i = 0, e = JT.size(); i != e; ++i) 667dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray NumEntries += JT[i].MBBs.size(); 668dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 669dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray unsigned EntrySize = MJTI->getEntrySize(); 670dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 671dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray return NumEntries * EntrySize; 672dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray} 673dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 674580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffraystatic uintptr_t RoundUpToAlign(uintptr_t Size, unsigned Alignment) { 675dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray if (Alignment == 0) Alignment = 1; 676580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray // Since we do not know where the buffer will be allocated, be pessimistic. 677580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray return Size + Alignment; 678dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray} 679be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng 680dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// addSizeOfGlobal - add the size of the global (plus any alignment padding) 681dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// into the running total Size. 682dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 683dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesenunsigned JITEmitter::addSizeOfGlobal(const GlobalVariable *GV, unsigned Size) { 684dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen const Type *ElTy = GV->getType()->getElementType(); 685dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen size_t GVSize = (size_t)TheJIT->getTargetData()->getABITypeSize(ElTy); 686dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen size_t GVAlign = 687dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen (size_t)TheJIT->getTargetData()->getPreferredAlignment(GV); 688eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: Adding in size " << GVSize << " alignment " << GVAlign; 689dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen DEBUG(GV->dump()); 690dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // Assume code section ends with worst possible alignment, so first 691dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // variable needs maximal padding. 692dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (Size==0) 693dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = 1; 694dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = ((Size+GVAlign-1)/GVAlign)*GVAlign; 695dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size += GVSize; 696dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen return Size; 697dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen} 698dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 699dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// addSizeOfGlobalsInConstantVal - find any globals that we haven't seen yet 700dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// but are referenced from the constant; put them in GVSet and add their 701dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// size into the running total Size. 702dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 703dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesenunsigned JITEmitter::addSizeOfGlobalsInConstantVal(const Constant *C, 704dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned Size) { 705dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // If its undefined, return the garbage. 706dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (isa<UndefValue>(C)) 707dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen return Size; 708dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 709dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // If the value is a ConstantExpr 710dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { 711dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Constant *Op0 = CE->getOperand(0); 712dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen switch (CE->getOpcode()) { 713dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::GetElementPtr: 714dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::Trunc: 715dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::ZExt: 716dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::SExt: 717dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::FPTrunc: 718dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::FPExt: 719dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::UIToFP: 720dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::SIToFP: 721dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::FPToUI: 722dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::FPToSI: 723dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::PtrToInt: 724dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::IntToPtr: 725dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::BitCast: { 726dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobalsInConstantVal(Op0, Size); 727dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen break; 728dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 729dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::Add: 730dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::Sub: 731dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::Mul: 732dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::UDiv: 733dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::SDiv: 734dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::URem: 735dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::SRem: 736dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::And: 737dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::Or: 738dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen case Instruction::Xor: { 739dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobalsInConstantVal(Op0, Size); 740dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobalsInConstantVal(CE->getOperand(1), Size); 741dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen break; 742dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 743dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen default: { 744dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen cerr << "ConstantExpr not handled: " << *CE << "\n"; 745dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen abort(); 746dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 747dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 748dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 749dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 750dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (C->getType()->getTypeID() == Type::PointerTyID) 751dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(C)) 75247c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng if (GVSet.insert(GV)) 753dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobal(GV, Size); 754dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 755dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen return Size; 756dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen} 757dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 758dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// addSizeOfGLobalsInInitializer - handle any globals that we haven't seen yet 759dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// but are referenced from the given initializer. 760dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 761dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesenunsigned JITEmitter::addSizeOfGlobalsInInitializer(const Constant *Init, 762dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned Size) { 763dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (!isa<UndefValue>(Init) && 764dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen !isa<ConstantVector>(Init) && 765dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen !isa<ConstantAggregateZero>(Init) && 766dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen !isa<ConstantArray>(Init) && 767dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen !isa<ConstantStruct>(Init) && 768dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Init->getType()->isFirstClassType()) 769dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobalsInConstantVal(Init, Size); 770dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen return Size; 771dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen} 772dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 773dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// GetSizeOfGlobalsInBytes - walk the code for the function, looking for 774dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// globals; then walk the initializers of those globals looking for more. 775dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// If their size has not been considered yet, add it into the running total 776dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen/// Size. 777dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 778dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesenunsigned JITEmitter::GetSizeOfGlobalsInBytes(MachineFunction &MF) { 779dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned Size = 0; 780dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen GVSet.clear(); 781dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 782dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); 783dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen MBB != E; ++MBB) { 784dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); 785dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen I != E; ++I) { 786dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen const TargetInstrDesc &Desc = I->getDesc(); 787dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen const MachineInstr &MI = *I; 788dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen unsigned NumOps = Desc.getNumOperands(); 789dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen for (unsigned CurOp = 0; CurOp < NumOps; CurOp++) { 790dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen const MachineOperand &MO = MI.getOperand(CurOp); 791d735b8019b0f297d7c14b55adcd887af24d8e602Dan Gohman if (MO.isGlobal()) { 792dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen GlobalValue* V = MO.getGlobal(); 793dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen const GlobalVariable *GV = dyn_cast<const GlobalVariable>(V); 794dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (!GV) 795dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen continue; 796dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // If seen in previous function, it will have an entry here. 797dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (TheJIT->getPointerToGlobalIfAvailable(GV)) 798dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen continue; 799dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // If seen earlier in this function, it will have an entry here. 800dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // FIXME: it should be possible to combine these tables, by 801dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // assuming the addresses of the new globals in this module 802dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // start at 0 (or something) and adjusting them after codegen 803dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // complete. Another possibility is to grab a marker bit in GV. 80447c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng if (GVSet.insert(GV)) 805dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // A variable as yet unseen. Add in its size. 806dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobal(GV, Size); 807dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 808dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 809dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 810dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 811eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: About to look through initializers\n"; 812dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // Look for more globals that are referenced only from initializers. 813dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // GVSet.end is computed each time because the set can grow as we go. 81447c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng for (SmallPtrSet<const GlobalVariable *, 8>::iterator I = GVSet.begin(); 815dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen I != GVSet.end(); I++) { 816dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen const GlobalVariable* GV = *I; 817dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen if (GV->hasInitializer()) 818dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen Size = addSizeOfGlobalsInInitializer(GV->getInitializer(), Size); 819dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen } 820dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 821dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen return Size; 822dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen} 823dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 824166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattnervoid JITEmitter::startFunction(MachineFunction &F) { 825eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: Starting CodeGen of Function " 826eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng << F.getFunction()->getName() << "\n"; 827eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng 828dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray uintptr_t ActualSize = 0; 829cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach // Set the memory writable, if it's not already 830cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach MemMgr->setMemoryWritable(); 8315913e6c5dbaff88ac00d5e679382abc72323831aNicolas Geoffray if (MemMgr->NeedsExactSize()) { 832eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: ExactSize\n"; 833dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray const TargetInstrInfo* TII = F.getTarget().getInstrInfo(); 834dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray MachineJumpTableInfo *MJTI = F.getJumpTableInfo(); 835dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray MachineConstantPool *MCP = F.getConstantPool(); 836dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 837dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Ensure the constant pool/jump table info is at least 4-byte aligned. 838580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray ActualSize = RoundUpToAlign(ActualSize, 16); 839dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 840dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Add the alignment of the constant pool 841580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray ActualSize = RoundUpToAlign(ActualSize, 842580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray 1 << MCP->getConstantPoolAlignment()); 843dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 844dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Add the constant pool size 845dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray ActualSize += GetConstantPoolSizeInBytes(MCP); 846dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 847dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Add the aligment of the jump table info 848580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray ActualSize = RoundUpToAlign(ActualSize, MJTI->getAlignment()); 849dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 850dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Add the jump table size 851dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray ActualSize += GetJumpTableSizeInBytes(MJTI); 852dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 853dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Add the alignment for the function 854580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray ActualSize = RoundUpToAlign(ActualSize, 855580631a73a71ff621c71618b16e9644b30a9d3c9Nicolas Geoffray std::max(F.getFunction()->getAlignment(), 8U)); 856dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 857dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray // Add the function size 858dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray ActualSize += TII->GetFunctionSizeInBytes(F); 859dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 860eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: ActualSize before globals " << ActualSize << "\n"; 861dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // Add the size of the globals that will be allocated after this function. 862dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // These are all the ones referenced from this function that were not 863dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen // previously allocated. 864dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen ActualSize += GetSizeOfGlobalsInBytes(F); 865eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: ActualSize after globals " << ActualSize << "\n"; 866dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray } 867dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 8688907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(), 8698907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner ActualSize); 870e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner BufferEnd = BufferBegin+ActualSize; 871f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 8729a1e9b91407f4752ff3de392d60a6cf3f1dcc37dEvan Cheng // Ensure the constant pool/jump table info is at least 4-byte aligned. 8739a1e9b91407f4752ff3de392d60a6cf3f1dcc37dEvan Cheng emitAlignment(16); 8749a1e9b91407f4752ff3de392d60a6cf3f1dcc37dEvan Cheng 875f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner emitConstantPool(F.getConstantPool()); 876f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner initJumpTableInfo(F.getJumpTableInfo()); 877f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 878f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner // About to start emitting the machine code for the function. 8790eb4d6b52e1b5db9a4c86e5a954356ae3507a287Chris Lattner emitAlignment(std::max(F.getFunction()->getAlignment(), 8U)); 880f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr); 88155fc28076fa48723bd170e51638b3b5974ca0fa1Evan Cheng 882b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner MBBLocations.clear(); 883bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner} 884bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner 88543b429b05989075b60693d57395c99b0ad789f8dChris Lattnerbool JITEmitter::finishFunction(MachineFunction &F) { 886e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner if (CurBufferPtr == BufferEnd) { 887e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner // FIXME: Allocate more space, then try again. 888832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling cerr << "JIT: Ran out of space for generated machine code!\n"; 889e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner abort(); 890e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner } 891e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 892b92767afd442a8363a8696e54880ee31c5d48c1eJim Laskey emitJumpTableInfo(F.getJumpTableInfo()); 893b4432f3d4754e16c918428d34a9d8ec18ab79204Chris Lattner 894a827953c32e420740c281b4a38a056d15b180932Chris Lattner // FnStart is the start of the text, not the start of the constant pool and 895a827953c32e420740c281b4a38a056d15b180932Chris Lattner // other per-function data. 896a827953c32e420740c281b4a38a056d15b180932Chris Lattner unsigned char *FnStart = 897a827953c32e420740c281b4a38a056d15b180932Chris Lattner (unsigned char *)TheJIT->getPointerToGlobalIfAvailable(F.getFunction()); 898bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner 8995be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner if (!Relocations.empty()) { 900e884dc2c586bc2f6646ffce89fef5100b412326eChris Lattner NumRelos += Relocations.size(); 901e884dc2c586bc2f6646ffce89fef5100b412326eChris Lattner 9025be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner // Resolve the relocations to concrete pointers. 9035be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { 9045be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner MachineRelocation &MR = Relocations[i]; 9059200605cd5f6db50be20efb7df926dc5a0d19a4dEvan Cheng void *ResultPtr = 0; 906ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng if (!MR.letTargetResolve()) { 907d7398c9b699cae3a109e9808401f7d0b2fc7e686Evan Cheng if (MR.isExternalSymbol()) { 908d7398c9b699cae3a109e9808401f7d0b2fc7e686Evan Cheng ResultPtr = TheJIT->getPointerToNamedFunction(MR.getExternalSymbol()); 909d7398c9b699cae3a109e9808401f7d0b2fc7e686Evan Cheng DOUT << "JIT: Map \'" << MR.getExternalSymbol() << "\' to [" 910ca66b08bc6c3cf899459e642a5297df8b9ccdb0dEvan Cheng << ResultPtr << "]\n"; 911ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng 912ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng // If the target REALLY wants a stub for this function, emit it now. 913ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng if (!MR.doesntNeedStub()) 914ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng ResultPtr = Resolver.getExternalFunctionStub(ResultPtr); 915ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng } else if (MR.isGlobalValue()) { 916ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng ResultPtr = getPointerToGlobal(MR.getGlobalValue(), 917ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng BufferBegin+MR.getMachineCodeOffset(), 918ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng MR.doesntNeedStub()); 9195594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng } else if (MR.isIndirectSymbol()) { 9205594f120b8880f7c514b0376c4adac1267a0b2b6Evan Cheng ResultPtr = getPointerToGVIndirectSym(MR.getGlobalValue(), 921be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng BufferBegin+MR.getMachineCodeOffset(), 922be8c03fc66b75fa775e1f47d62a1b0d803fced1cEvan Cheng MR.doesntNeedStub()); 923ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng } else if (MR.isBasicBlock()) { 924ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock()); 925ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng } else if (MR.isConstantPoolIndex()) { 926ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng ResultPtr = (void*)getConstantPoolEntryAddress(MR.getConstantPoolIndex()); 927ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng } else { 928ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng assert(MR.isJumpTableIndex()); 929ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng ResultPtr=(void*)getJumpTableEntryAddress(MR.getJumpTableIndex()); 930ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng } 93100b16889ab461b7ecef1c91ade101186b7f1fce2Jeff Cohen 932ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng MR.setResultPointer(ResultPtr); 933ef5784ef9b9cdfbc9819a96440c6873196eade76Evan Cheng } 93416ec33c6ef630730ad55a4af7242c658e1efb8b3Andrew Lenharth 9356a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth // if we are managing the GOT and the relocation wants an index, 9366a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth // give it one 9378907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner if (MR.isGOTRelative() && MemMgr->isManagingGOT()) { 938e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner unsigned idx = Resolver.getGOTIndexForAddr(ResultPtr); 9396a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth MR.setGOTIndex(idx); 9408907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner if (((void**)MemMgr->getGOTBase())[idx] != ResultPtr) { 941eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: GOT was out of date for " << ResultPtr 9428907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] 943832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << "\n"; 9448907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner ((void**)MemMgr->getGOTBase())[idx] = ResultPtr; 9456a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth } 94616ec33c6ef630730ad55a4af7242c658e1efb8b3Andrew Lenharth } 9475be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner } 9485be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner 94943b429b05989075b60693d57395c99b0ad789f8dChris Lattner TheJIT->getJITInfo().relocate(BufferBegin, &Relocations[0], 9508907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner Relocations.size(), MemMgr->getGOTBase()); 9515be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner } 9525be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner 953d2d5c76753b132c34c71248db2f136b38531bc6dChris Lattner // Update the GOT entry for F to point to the new code. 9548907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner if (MemMgr->isManagingGOT()) { 955e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner unsigned idx = Resolver.getGOTIndexForAddr((void*)BufferBegin); 9568907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner if (((void**)MemMgr->getGOTBase())[idx] != (void*)BufferBegin) { 957eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << "JIT: GOT was out of date for " << (void*)BufferBegin 9588907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] << "\n"; 9598907b4ba479bbfbe630a4c3abab32c7d49749a48Chris Lattner ((void**)MemMgr->getGOTBase())[idx] = (void*)BufferBegin; 9606a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth } 9616a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth } 9626a9746127a168306a670eaff11925605dbea9d4fAndrew Lenharth 963cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes unsigned char *FnEnd = CurBufferPtr; 964cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes 965cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes MemMgr->endFunctionBody(F.getFunction(), BufferBegin, FnEnd); 9665788d1a169db3346a612a13113348d2709bdd15bEvan Cheng 9675788d1a169db3346a612a13113348d2709bdd15bEvan Cheng if (CurBufferPtr == BufferEnd) { 9685788d1a169db3346a612a13113348d2709bdd15bEvan Cheng // FIXME: Allocate more space, then try again. 9695788d1a169db3346a612a13113348d2709bdd15bEvan Cheng cerr << "JIT: Ran out of space for generated machine code!\n"; 9705788d1a169db3346a612a13113348d2709bdd15bEvan Cheng abort(); 9715788d1a169db3346a612a13113348d2709bdd15bEvan Cheng } 9725788d1a169db3346a612a13113348d2709bdd15bEvan Cheng 973cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes BufferBegin = CurBufferPtr = 0; 974cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes NumBytes += FnEnd-FnStart; 975cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes 97655fc28076fa48723bd170e51638b3b5974ca0fa1Evan Cheng // Invalidate the icache if necessary. 977bc52cada0933f353d30da7b49af9a641bdb2c57dChris Lattner sys::Memory::InvalidateInstructionCache(FnStart, FnEnd-FnStart); 9788ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 9798ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner // Add it to the JIT symbol table if the host wants it. 9808ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner AddFunctionToSymbolTable(F.getFunction()->getNameStart(), 9818ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner FnStart, FnEnd-FnStart); 98255fc28076fa48723bd170e51638b3b5974ca0fa1Evan Cheng 983832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling DOUT << "JIT: Finished CodeGen of [" << (void*)FnStart 984832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << "] Function: " << F.getFunction()->getName() 985832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << ": " << (FnEnd-FnStart) << " bytes of text, " 986832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << Relocations.size() << " relocations\n"; 9875be478f360b4c632d1adfccc64df87840e1ccfc1Chris Lattner Relocations.clear(); 9888cd4c3e6534a14566bf163301fd45bca34e655c1Anton Korobeynikov 989bc4707a2554ac04ba006bf70035e7bc7270236a9Evan Cheng // Mark code region readable and executable if it's not so already. 990cce6c297c54b4c9c8615c77e97cd64e70812ea60Jim Grosbach MemMgr->setMemoryExecutable(); 991bc4707a2554ac04ba006bf70035e7bc7270236a9Evan Cheng 992c5633c235e94f69c6a77e894bcc84d8ba71106f0Chris Lattner#ifndef NDEBUG 993a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng { 994e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng if (sys::hasDisassembler()) { 995e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng DOUT << "JIT: Disassembled code:\n"; 996eb5d95a22df7ab88815f35bdc8b6e5d3a6a1119dEvan Cheng DOUT << sys::disassembleBuffer(FnStart, FnEnd-FnStart, (uintptr_t)FnStart); 997e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng } else { 998e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng DOUT << "JIT: Binary code:\n"; 999a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng DOUT << std::hex; 1000a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng unsigned char* q = FnStart; 1001e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng for (int i = 0; q < FnEnd; q += 4, ++i) { 1002e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng if (i == 4) 1003e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng i = 0; 1004e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng if (i == 0) 1005e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng DOUT << "JIT: " << std::setw(8) << std::setfill('0') 1006e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng << (long)(q - FnStart) << ": "; 1007e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng bool Done = false; 1008e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng for (int j = 3; j >= 0; --j) { 1009e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng if (q + j >= FnEnd) 1010e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng Done = true; 1011e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng else 1012e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng DOUT << std::setw(2) << std::setfill('0') << (unsigned short)q[j]; 1013e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng } 1014e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng if (Done) 1015e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng break; 1016e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng DOUT << ' '; 1017e7c3551e6f75ca3fc8a3a30e8ca5f9c19edbe2e3Evan Cheng if (i == 3) 10186863fb033a9079e04edc7a568e34098bcf5b9ebeEvan Cheng DOUT << '\n'; 1019a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng } 1020a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng DOUT << std::dec; 10216863fb033a9079e04edc7a568e34098bcf5b9ebeEvan Cheng DOUT<< '\n'; 1022a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng } 1023a7916f586d438b0e626e54ce713435437c4b901cEvan Cheng } 1024c5633c235e94f69c6a77e894bcc84d8ba71106f0Chris Lattner#endif 1025afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray if (ExceptionHandling) { 1026dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray uintptr_t ActualSize = 0; 1027afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray SavedBufferBegin = BufferBegin; 1028afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray SavedBufferEnd = BufferEnd; 1029afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray SavedCurBufferPtr = CurBufferPtr; 1030dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray 10315913e6c5dbaff88ac00d5e679382abc72323831aNicolas Geoffray if (MemMgr->NeedsExactSize()) { 10325913e6c5dbaff88ac00d5e679382abc72323831aNicolas Geoffray ActualSize = DE->GetDwarfTableSizeInBytes(F, *this, FnStart, FnEnd); 1033dc17ab2bf0c4d325b87ac8130004ab11f3f7106dNicolas Geoffray } 1034afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 1035afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(), 1036afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray ActualSize); 1037afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray BufferEnd = BufferBegin+ActualSize; 1038afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray unsigned char* FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd); 10390fdaa0b8f194f0ef7cec0610c50672b89bd7c17aChris Lattner MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr, 10400fdaa0b8f194f0ef7cec0610c50672b89bd7c17aChris Lattner FrameRegister); 1041afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray BufferBegin = SavedBufferBegin; 1042afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray BufferEnd = SavedBufferEnd; 1043afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray CurBufferPtr = SavedCurBufferPtr; 1044afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 1045afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray TheJIT->RegisterTable(FrameRegister); 1046afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray } 1047252ddfbdbc834d1abe80de9c2205afac7918d3eaEvan Cheng 1048252ddfbdbc834d1abe80de9c2205afac7918d3eaEvan Cheng if (MMI) 1049252ddfbdbc834d1abe80de9c2205afac7918d3eaEvan Cheng MMI->EndFunction(); 1050afe6c2b001a924cd74bd0aacfed5984d9af004b0Nicolas Geoffray 105143b429b05989075b60693d57395c99b0ad789f8dChris Lattner return false; 1052bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner} 1053bd199fb1148b9e16c4e6f3d0ee386c2505a55b71Chris Lattner 10545788d1a169db3346a612a13113348d2709bdd15bEvan Chengvoid* JITEmitter::allocateSpace(uintptr_t Size, unsigned Alignment) { 1055cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes if (BufferBegin) 1056cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes return MachineCodeEmitter::allocateSpace(Size, Alignment); 1057cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes 1058cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes // create a new memory block if there is no active one. 1059cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes // care must be taken so that BufferBegin is invalidated when a 1060cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes // block is trimmed 1061cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes BufferBegin = CurBufferPtr = MemMgr->allocateSpace(Size, Alignment); 1062cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes BufferEnd = BufferBegin+Size; 1063cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes return CurBufferPtr; 1064cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes} 1065cef7527a85d026aeb17a4dacca73c70c0ab5da40Nuno Lopes 1066166f2269f5e5e54f8b5df705e7653929374d1893Chris Lattnervoid JITEmitter::emitConstantPool(MachineConstantPool *MCP) { 106747c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng if (TheJIT->getJITInfo().hasCustomConstantPool()) 10688fe95356dd487a79145ec07a9f46cd743b4c9bddJim Grosbach return; 106947c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng 1070fa77d43ba1d91ed39f46e11caeb28dcabae9e193Chris Lattner const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants(); 10712c0a6a19ef42f2ad547dbc0693e55e082a21ac8bChris Lattner if (Constants.empty()) return; 10722c0a6a19ef42f2ad547dbc0693e55e082a21ac8bChris Lattner 1073cd5731d98b15c9de236bd0dd6c9c57d9bcecbcebEvan Cheng MachineConstantPoolEntry CPE = Constants.back(); 1074cd5731d98b15c9de236bd0dd6c9c57d9bcecbcebEvan Cheng unsigned Size = CPE.Offset; 1075cd5731d98b15c9de236bd0dd6c9c57d9bcecbcebEvan Cheng const Type *Ty = CPE.isMachineConstantPoolEntry() 10768a650095fcecaf5270231bd376e49ed46249da95Chris Lattner ? CPE.Val.MachineCPVal->getType() : CPE.Val.ConstVal->getType(); 1077514ab348fddcdffa8367685dc608b2f8d5de986dDuncan Sands Size += TheJIT->getTargetData()->getABITypeSize(Ty); 10783029f920519e0871a5aad5d7c592281093953733Chris Lattner 107997b8c40d095c4eb5d8e8ff5ac6da567f043bd8baEvan Cheng unsigned Align = 1 << MCP->getConstantPoolAlignment(); 108097b8c40d095c4eb5d8e8ff5ac6da567f043bd8baEvan Cheng ConstantPoolBase = allocateSpace(Size, Align); 1081239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner ConstantPool = MCP; 1082f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 1083f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner if (ConstantPoolBase == 0) return; // Buffer overflow. 1084f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 108597b8c40d095c4eb5d8e8ff5ac6da567f043bd8baEvan Cheng DOUT << "JIT: Emitted constant pool at [" << ConstantPoolBase 108697b8c40d095c4eb5d8e8ff5ac6da567f043bd8baEvan Cheng << "] (size: " << Size << ", alignment: " << Align << ")\n"; 108797b8c40d095c4eb5d8e8ff5ac6da567f043bd8baEvan Cheng 1088239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner // Initialize the memory for all of the constant pool entries. 10893029f920519e0871a5aad5d7c592281093953733Chris Lattner for (unsigned i = 0, e = Constants.size(); i != e; ++i) { 1090239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner void *CAddr = (char*)ConstantPoolBase+Constants[i].Offset; 1091cd5731d98b15c9de236bd0dd6c9c57d9bcecbcebEvan Cheng if (Constants[i].isMachineConstantPoolEntry()) { 1092cd5731d98b15c9de236bd0dd6c9c57d9bcecbcebEvan Cheng // FIXME: add support to lower machine constant pool values into bytes! 1093832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling cerr << "Initialize memory with machine specific constant pool entry" 1094832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling << " has not been implemented!\n"; 1095cd5731d98b15c9de236bd0dd6c9c57d9bcecbcebEvan Cheng abort(); 1096cd5731d98b15c9de236bd0dd6c9c57d9bcecbcebEvan Cheng } 1097cd5731d98b15c9de236bd0dd6c9c57d9bcecbcebEvan Cheng TheJIT->InitializeMemory(Constants[i].Val.ConstVal, CAddr); 109897b8c40d095c4eb5d8e8ff5ac6da567f043bd8baEvan Cheng DOUT << "JIT: CP" << i << " at [" << CAddr << "]\n"; 10991cc08381f1ab57efdf07248fd5e9fd75ef6f0f99Chris Lattner } 11001cc08381f1ab57efdf07248fd5e9fd75ef6f0f99Chris Lattner} 11011cc08381f1ab57efdf07248fd5e9fd75ef6f0f99Chris Lattner 110237efe6764568a3829fee26aba532283131d1a104Nate Begemanvoid JITEmitter::initJumpTableInfo(MachineJumpTableInfo *MJTI) { 110347c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng if (TheJIT->getJITInfo().hasCustomJumpTables()) 110447c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng return; 110547c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng 110637efe6764568a3829fee26aba532283131d1a104Nate Begeman const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 110737efe6764568a3829fee26aba532283131d1a104Nate Begeman if (JT.empty()) return; 110837efe6764568a3829fee26aba532283131d1a104Nate Begeman 1109f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner unsigned NumEntries = 0; 111037efe6764568a3829fee26aba532283131d1a104Nate Begeman for (unsigned i = 0, e = JT.size(); i != e; ++i) 1111f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner NumEntries += JT[i].MBBs.size(); 1112f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 1113f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner unsigned EntrySize = MJTI->getEntrySize(); 1114f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner 111537efe6764568a3829fee26aba532283131d1a104Nate Begeman // Just allocate space for all the jump tables now. We will fix up the actual 111637efe6764568a3829fee26aba532283131d1a104Nate Begeman // MBB entries in the tables after we emit the code for each block, since then 111737efe6764568a3829fee26aba532283131d1a104Nate Begeman // we will know the final locations of the MBBs in memory. 111837efe6764568a3829fee26aba532283131d1a104Nate Begeman JumpTable = MJTI; 1119f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner JumpTableBase = allocateSpace(NumEntries * EntrySize, MJTI->getAlignment()); 112037efe6764568a3829fee26aba532283131d1a104Nate Begeman} 112137efe6764568a3829fee26aba532283131d1a104Nate Begeman 1122b92767afd442a8363a8696e54880ee31c5d48c1eJim Laskeyvoid JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { 112347c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng if (TheJIT->getJITInfo().hasCustomJumpTables()) 112447c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng return; 112547c01a0099c10c031f8c544baf44b1c3a1de3fadEvan Cheng 112637efe6764568a3829fee26aba532283131d1a104Nate Begeman const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 1127f75f9be3fb89eb6661a0ed8bfee8a6328ee5a4d1Chris Lattner if (JT.empty() || JumpTableBase == 0) return; 112837efe6764568a3829fee26aba532283131d1a104Nate Begeman 1129b92767afd442a8363a8696e54880ee31c5d48c1eJim Laskey if (TargetMachine::getRelocationModel() == Reloc::PIC_) { 1130acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey assert(MJTI->getEntrySize() == 4 && "Cross JIT'ing?"); 1131acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // For each jump table, place the offset from the beginning of the table 1132acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // to the target address. 1133acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey int *SlotPtr = (int*)JumpTableBase; 1134acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey 1135acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey for (unsigned i = 0, e = JT.size(); i != e; ++i) { 1136acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs; 1137acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // Store the offset of the basic block for this jump table slot in the 1138acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // memory we allocated for the jump table in 'initJumpTableInfo' 11395788d1a169db3346a612a13113348d2709bdd15bEvan Cheng uintptr_t Base = (uintptr_t)SlotPtr; 11402a3e08b5961353fa3faeadf81f481ae9f5463427Evan Cheng for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { 11415788d1a169db3346a612a13113348d2709bdd15bEvan Cheng uintptr_t MBBAddr = getMachineBasicBlockAddress(MBBs[mi]); 11422a3e08b5961353fa3faeadf81f481ae9f5463427Evan Cheng *SlotPtr++ = TheJIT->getJITInfo().getPICJumpTableEntry(MBBAddr, Base); 11432a3e08b5961353fa3faeadf81f481ae9f5463427Evan Cheng } 1144acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey } 1145acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey } else { 1146acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey assert(MJTI->getEntrySize() == sizeof(void*) && "Cross JIT'ing?"); 1147acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey 1148acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // For each jump table, map each target in the jump table to the address of 1149acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // an emitted MachineBasicBlock. 1150acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey intptr_t *SlotPtr = (intptr_t*)JumpTableBase; 1151acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey 1152acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey for (unsigned i = 0, e = JT.size(); i != e; ++i) { 1153acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs; 1154acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // Store the address of the basic block for this jump table slot in the 1155acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey // memory we allocated for the jump table in 'initJumpTableInfo' 1156acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) 1157acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey *SlotPtr++ = getMachineBasicBlockAddress(MBBs[mi]); 1158acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey } 115937efe6764568a3829fee26aba532283131d1a104Nate Begeman } 116037efe6764568a3829fee26aba532283131d1a104Nate Begeman} 116137efe6764568a3829fee26aba532283131d1a104Nate Begeman 1162ce4a70bd7608861e104b04265a0c71e5df8ecefeEvan Chengvoid JITEmitter::startGVStub(const GlobalValue* GV, unsigned StubSize, 1163ce4a70bd7608861e104b04265a0c71e5df8ecefeEvan Cheng unsigned Alignment) { 116443b429b05989075b60693d57395c99b0ad789f8dChris Lattner SavedBufferBegin = BufferBegin; 116543b429b05989075b60693d57395c99b0ad789f8dChris Lattner SavedBufferEnd = BufferEnd; 116643b429b05989075b60693d57395c99b0ad789f8dChris Lattner SavedCurBufferPtr = CurBufferPtr; 116743b429b05989075b60693d57395c99b0ad789f8dChris Lattner 1168ce4a70bd7608861e104b04265a0c71e5df8ecefeEvan Cheng BufferBegin = CurBufferPtr = MemMgr->allocateStub(GV, StubSize, Alignment); 116943b429b05989075b60693d57395c99b0ad789f8dChris Lattner BufferEnd = BufferBegin+StubSize+1; 11706125fddb52c3d821a4e4c000cbd210428b0009f6Chris Lattner} 11716125fddb52c3d821a4e4c000cbd210428b0009f6Chris Lattner 1172ce4a70bd7608861e104b04265a0c71e5df8ecefeEvan Chengvoid *JITEmitter::finishGVStub(const GlobalValue* GV) { 117343b429b05989075b60693d57395c99b0ad789f8dChris Lattner NumBytes += getCurrentPCOffset(); 117443b429b05989075b60693d57395c99b0ad789f8dChris Lattner std::swap(SavedBufferBegin, BufferBegin); 117543b429b05989075b60693d57395c99b0ad789f8dChris Lattner BufferEnd = SavedBufferEnd; 117643b429b05989075b60693d57395c99b0ad789f8dChris Lattner CurBufferPtr = SavedCurBufferPtr; 117743b429b05989075b60693d57395c99b0ad789f8dChris Lattner return SavedBufferBegin; 1178bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner} 1179bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner 1180bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner// getConstantPoolEntryAddress - Return the address of the 'ConstantNum' entry 1181bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner// in the constant pool that was last emitted with the 'emitConstantPool' 1182bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner// method. 1183bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner// 11845788d1a169db3346a612a13113348d2709bdd15bEvan Chenguintptr_t JITEmitter::getConstantPoolEntryAddress(unsigned ConstantNum) const { 1185239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner assert(ConstantNum < ConstantPool->getConstants().size() && 11863c94497ec7852eccd68c1bc1663e8ac2a7bb1ab9Misha Brukman "Invalid ConstantPoolIndex!"); 11875788d1a169db3346a612a13113348d2709bdd15bEvan Cheng return (uintptr_t)ConstantPoolBase + 1188239862ce995adfd3b51062e62e54ef2db92b1150Chris Lattner ConstantPool->getConstants()[ConstantNum].Offset; 1189bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner} 1190bba1b6df9a7ac36e3a479dfe953a9618c87db7bbChris Lattner 119137efe6764568a3829fee26aba532283131d1a104Nate Begeman// getJumpTableEntryAddress - Return the address of the JumpTable with index 119237efe6764568a3829fee26aba532283131d1a104Nate Begeman// 'Index' in the jumpp table that was last initialized with 'initJumpTableInfo' 119337efe6764568a3829fee26aba532283131d1a104Nate Begeman// 11945788d1a169db3346a612a13113348d2709bdd15bEvan Chenguintptr_t JITEmitter::getJumpTableEntryAddress(unsigned Index) const { 119537efe6764568a3829fee26aba532283131d1a104Nate Begeman const std::vector<MachineJumpTableEntry> &JT = JumpTable->getJumpTables(); 119637efe6764568a3829fee26aba532283131d1a104Nate Begeman assert(Index < JT.size() && "Invalid jump table index!"); 119737efe6764568a3829fee26aba532283131d1a104Nate Begeman 119837efe6764568a3829fee26aba532283131d1a104Nate Begeman unsigned Offset = 0; 119937efe6764568a3829fee26aba532283131d1a104Nate Begeman unsigned EntrySize = JumpTable->getEntrySize(); 120037efe6764568a3829fee26aba532283131d1a104Nate Begeman 120137efe6764568a3829fee26aba532283131d1a104Nate Begeman for (unsigned i = 0; i < Index; ++i) 1202acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey Offset += JT[i].MBBs.size(); 1203acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey 1204acd80ac7bb19f8bdfa55336d567c9ecbe695c8b8Jim Laskey Offset *= EntrySize; 120537efe6764568a3829fee26aba532283131d1a104Nate Begeman 12065788d1a169db3346a612a13113348d2709bdd15bEvan Cheng return (uintptr_t)((char *)JumpTableBase + Offset); 120737efe6764568a3829fee26aba532283131d1a104Nate Begeman} 120837efe6764568a3829fee26aba532283131d1a104Nate Begeman 1209e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner//===----------------------------------------------------------------------===// 1210e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner// Public interface to this file 1211e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner//===----------------------------------------------------------------------===// 1212e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 12139f2f142d255bc96f109dd5c6524a485937b1f3a1Chris LattnerMachineCodeEmitter *JIT::createEmitter(JIT &jit, JITMemoryManager *JMM) { 12149f2f142d255bc96f109dd5c6524a485937b1f3a1Chris Lattner return new JITEmitter(jit, JMM); 1215e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner} 1216e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 1217d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman// getPointerToNamedFunction - This function is used as a global wrapper to 12184d326fa9bea5b80147edf14d1521fc41ce315275Chris Lattner// JIT::getPointerToNamedFunction for the purpose of resolving symbols when 1219d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman// bugpoint is debugging the JIT. In that scenario, we are loading an .so and 1220d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman// need to resolve function(s) that are being mis-codegenerated, so we need to 1221d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman// resolve their addresses at runtime, and this is the way to do it. 1222d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukmanextern "C" { 1223d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman void *getPointerToNamedFunction(const char *Name) { 1224fe854034677f59baca1e38075e71f6efca247a03Chris Lattner if (Function *F = TheJIT->FindFunctionNamed(Name)) 12254d326fa9bea5b80147edf14d1521fc41ce315275Chris Lattner return TheJIT->getPointerToFunction(F); 12264d326fa9bea5b80147edf14d1521fc41ce315275Chris Lattner return TheJIT->getPointerToNamedFunction(Name); 1227d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman } 1228d69c1e6dc28bed3c156f78fee5253748e3d509e2Misha Brukman} 1229e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 1230e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner// getPointerToFunctionOrStub - If the specified function has been 1231e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner// code-gen'd, return a pointer to the function. If not, compile it, or use 1232e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner// a stub to implement lazy compilation if available. 1233e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner// 1234e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattnervoid *JIT::getPointerToFunctionOrStub(Function *F) { 1235e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner // If we have already code generated the function, just return the address. 1236e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner if (void *Addr = getPointerToGlobalIfAvailable(F)) 1237e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner return Addr; 1238e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 1239e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner // Get a stub if the target supports it. 1240a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng assert(isa<JITEmitter>(MCE) && "Unexpected MCE?"); 1241a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng JITEmitter *JE = cast<JITEmitter>(getCodeEmitter()); 1242e748401b180d7041738e14d3896ac61ca4bdfcbaChris Lattner return JE->getJITResolver().getFunctionStub(F); 1243e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner} 1244e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 1245e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner/// freeMachineCodeForFunction - release machine code memory for given Function. 1246e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner/// 1247e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattnervoid JIT::freeMachineCodeForFunction(Function *F) { 1248dd947ea3c5e020c33c58a31939561265b980a3adDale Johannesen 1249e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner // Delete translation for this from the ExecutionEngine, so it will get 1250e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner // retranslated next time it is used. 12518ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner void *OldPtr = updateGlobalMapping(F, 0); 12528ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner 12538ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner if (OldPtr) 12548ac66c122b099bc3eab858bfc18f3cb342efc818Chris Lattner RemoveFunctionFromSymbolTable(OldPtr); 1255e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 1256e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner // Free the actual memory for the function body and related stuff. 1257a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng assert(isa<JITEmitter>(MCE) && "Unexpected MCE?"); 1258a044dfcb5ae3b789799cefaf5c4c2e1973fbf4c5Evan Cheng cast<JITEmitter>(MCE)->deallocateMemForFunction(F); 1259e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner} 1260e993cc27ad9fd84e6aaf652c94eb9ca0cb63a898Chris Lattner 1261