| Chris Lattner | 166f226 | 2004-11-22 22:00:25 +0000 | [diff] [blame] | 1 | //===-- JITEmitter.cpp - Write machine code to executable memory ----------===// | 
| Misha Brukman | f976c85 | 2005-04-21 22:55:34 +0000 | [diff] [blame] | 2 | // | 
| John Criswell | b576c94 | 2003-10-20 19:43:21 +0000 | [diff] [blame] | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | 4ee451d | 2007-12-29 20:36:04 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
| Misha Brukman | f976c85 | 2005-04-21 22:55:34 +0000 | [diff] [blame] | 7 | // | 
| John Criswell | b576c94 | 2003-10-20 19:43:21 +0000 | [diff] [blame] | 8 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | bd199fb | 2002-12-24 00:01:05 +0000 | [diff] [blame] | 9 | // | 
| Chris Lattner | 5be478f | 2004-11-20 03:46:14 +0000 | [diff] [blame] | 10 | // This file defines a MachineCodeEmitter object that is used by the JIT to | 
|  | 11 | // write machine code to memory and remember where relocatable values are. | 
| Chris Lattner | bd199fb | 2002-12-24 00:01:05 +0000 | [diff] [blame] | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
| Chris Lattner | 3785fad | 2003-08-05 17:00:32 +0000 | [diff] [blame] | 15 | #define DEBUG_TYPE "jit" | 
| Chris Lattner | 4d326fa | 2003-12-20 01:46:27 +0000 | [diff] [blame] | 16 | #include "JIT.h" | 
| Reid Kleckner | 2763217 | 2009-09-20 23:52:43 +0000 | [diff] [blame] | 17 | #include "JITDebugRegisterer.h" | 
| Nicolas Geoffray | afe6c2b | 2008-02-13 18:39:37 +0000 | [diff] [blame] | 18 | #include "JITDwarfEmitter.h" | 
| Reid Kleckner | 2763217 | 2009-09-20 23:52:43 +0000 | [diff] [blame] | 19 | #include "llvm/ADT/OwningPtr.h" | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 20 | #include "llvm/Constants.h" | 
| Chris Lattner | 2c0a6a1 | 2003-11-30 04:23:21 +0000 | [diff] [blame] | 21 | #include "llvm/Module.h" | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 22 | #include "llvm/DerivedTypes.h" | 
| Bruno Cardoso Lopes | a3f99f9 | 2009-05-30 20:51:52 +0000 | [diff] [blame] | 23 | #include "llvm/CodeGen/JITCodeEmitter.h" | 
| Chris Lattner | bd199fb | 2002-12-24 00:01:05 +0000 | [diff] [blame] | 24 | #include "llvm/CodeGen/MachineFunction.h" | 
| Chris Lattner | 1cc0838 | 2003-01-13 01:00:12 +0000 | [diff] [blame] | 25 | #include "llvm/CodeGen/MachineConstantPool.h" | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 26 | #include "llvm/CodeGen/MachineJumpTableInfo.h" | 
| Nicolas Geoffray | afe6c2b | 2008-02-13 18:39:37 +0000 | [diff] [blame] | 27 | #include "llvm/CodeGen/MachineModuleInfo.h" | 
| Chris Lattner | 5be478f | 2004-11-20 03:46:14 +0000 | [diff] [blame] | 28 | #include "llvm/CodeGen/MachineRelocation.h" | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 29 | #include "llvm/ExecutionEngine/GenericValue.h" | 
| Jeffrey Yasskin | df5a7da | 2009-06-25 02:04:04 +0000 | [diff] [blame] | 30 | #include "llvm/ExecutionEngine/JITEventListener.h" | 
|  | 31 | #include "llvm/ExecutionEngine/JITMemoryManager.h" | 
| Argyrios Kyrtzidis | b3a847d | 2009-05-18 21:06:40 +0000 | [diff] [blame] | 32 | #include "llvm/CodeGen/MachineCodeInfo.h" | 
| Chris Lattner | 1cc0838 | 2003-01-13 01:00:12 +0000 | [diff] [blame] | 33 | #include "llvm/Target/TargetData.h" | 
| Chris Lattner | 5be478f | 2004-11-20 03:46:14 +0000 | [diff] [blame] | 34 | #include "llvm/Target/TargetJITInfo.h" | 
| Jim Laskey | acd80ac | 2006-12-14 19:17:33 +0000 | [diff] [blame] | 35 | #include "llvm/Target/TargetMachine.h" | 
| Nicolas Geoffray | afe6c2b | 2008-02-13 18:39:37 +0000 | [diff] [blame] | 36 | #include "llvm/Target/TargetOptions.h" | 
| Reid Spencer | 551ccae | 2004-09-01 22:55:40 +0000 | [diff] [blame] | 37 | #include "llvm/Support/Debug.h" | 
| Torok Edwin | 7d696d8 | 2009-07-11 13:10:19 +0000 | [diff] [blame] | 38 | #include "llvm/Support/ErrorHandling.h" | 
| Chris Lattner | e7fd553 | 2006-05-08 22:00:52 +0000 | [diff] [blame] | 39 | #include "llvm/Support/MutexGuard.h" | 
| Nick Lewycky | 848b314 | 2009-04-19 18:32:03 +0000 | [diff] [blame] | 40 | #include "llvm/Support/ValueHandle.h" | 
| Torok Edwin | 7d696d8 | 2009-07-11 13:10:19 +0000 | [diff] [blame] | 41 | #include "llvm/Support/raw_ostream.h" | 
| Anton Korobeynikov | fd58e6e | 2007-01-23 10:26:08 +0000 | [diff] [blame] | 42 | #include "llvm/System/Disassembler.h" | 
| Chris Lattner | bc52cad | 2008-06-25 17:18:44 +0000 | [diff] [blame] | 43 | #include "llvm/System/Memory.h" | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 44 | #include "llvm/Target/TargetInstrInfo.h" | 
| Jeffrey Yasskin | 1e86132 | 2009-10-20 18:13:21 +0000 | [diff] [blame] | 45 | #include "llvm/ADT/DenseMap.h" | 
| Evan Cheng | 47c01a0 | 2008-11-07 09:02:17 +0000 | [diff] [blame] | 46 | #include "llvm/ADT/SmallPtrSet.h" | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 47 | #include "llvm/ADT/SmallVector.h" | 
| Reid Spencer | 551ccae | 2004-09-01 22:55:40 +0000 | [diff] [blame] | 48 | #include "llvm/ADT/Statistic.h" | 
| Jeffrey Yasskin | 23e5fcf | 2009-10-23 22:37:43 +0000 | [diff] [blame] | 49 | #include "llvm/ADT/ValueMap.h" | 
| Andrew Lenharth | a00269b | 2005-07-29 23:40:16 +0000 | [diff] [blame] | 50 | #include <algorithm> | 
| Evan Cheng | a7916f5 | 2008-11-05 23:44:08 +0000 | [diff] [blame] | 51 | #ifndef NDEBUG | 
|  | 52 | #include <iomanip> | 
|  | 53 | #endif | 
| Chris Lattner | c19aade | 2003-12-08 08:06:28 +0000 | [diff] [blame] | 54 | using namespace llvm; | 
| Brian Gaeke | d0fde30 | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 55 |  | 
| Chris Lattner | 3634373 | 2006-12-19 22:43:32 +0000 | [diff] [blame] | 56 | STATISTIC(NumBytes, "Number of bytes of machine code compiled"); | 
|  | 57 | STATISTIC(NumRelos, "Number of relocations applied"); | 
| Reid Kleckner | 10b4fc5 | 2009-07-23 21:46:56 +0000 | [diff] [blame] | 58 | STATISTIC(NumRetries, "Number of retries with more memory"); | 
| Chris Lattner | 3634373 | 2006-12-19 22:43:32 +0000 | [diff] [blame] | 59 | static JIT *TheJIT = 0; | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 60 |  | 
| Andrew Lenharth | a00269b | 2005-07-29 23:40:16 +0000 | [diff] [blame] | 61 |  | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 62 | //===----------------------------------------------------------------------===// | 
|  | 63 | // JIT lazy compilation code. | 
|  | 64 | // | 
|  | 65 | namespace { | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 66 | class JITEmitter; | 
| Jeffrey Yasskin | 23e5fcf | 2009-10-23 22:37:43 +0000 | [diff] [blame] | 67 | class JITResolverState; | 
|  | 68 |  | 
|  | 69 | template<typename ValueTy> | 
|  | 70 | struct NoRAUWValueMapConfig : public ValueMapConfig<ValueTy> { | 
|  | 71 | typedef JITResolverState *ExtraData; | 
|  | 72 | static void onRAUW(JITResolverState *, Value *Old, Value *New) { | 
|  | 73 | assert(false && "The JIT doesn't know how to handle a" | 
|  | 74 | " RAUW on a value it has emitted."); | 
|  | 75 | } | 
|  | 76 | }; | 
|  | 77 |  | 
|  | 78 | struct CallSiteValueMapConfig : public NoRAUWValueMapConfig<Function*> { | 
|  | 79 | typedef JITResolverState *ExtraData; | 
|  | 80 | static void onDelete(JITResolverState *JRS, Function *F); | 
|  | 81 | }; | 
|  | 82 |  | 
| Reid Spencer | ee44863 | 2005-07-12 15:51:55 +0000 | [diff] [blame] | 83 | class JITResolverState { | 
| Nick Lewycky | e2bcf13 | 2009-04-27 05:09:44 +0000 | [diff] [blame] | 84 | public: | 
| Jeffrey Yasskin | 23e5fcf | 2009-10-23 22:37:43 +0000 | [diff] [blame] | 85 | typedef ValueMap<Function*, void*, NoRAUWValueMapConfig<Function*> > | 
|  | 86 | FunctionToStubMapTy; | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 87 | typedef std::map<void*, AssertingVH<Function> > CallSiteToFunctionMapTy; | 
| Jeffrey Yasskin | 23e5fcf | 2009-10-23 22:37:43 +0000 | [diff] [blame] | 88 | typedef ValueMap<Function *, SmallPtrSet<void*, 1>, | 
|  | 89 | CallSiteValueMapConfig> FunctionToCallSitesMapTy; | 
| Nick Lewycky | e2bcf13 | 2009-04-27 05:09:44 +0000 | [diff] [blame] | 90 | typedef std::map<AssertingVH<GlobalValue>, void*> GlobalToIndirectSymMapTy; | 
| Reid Spencer | ee44863 | 2005-07-12 15:51:55 +0000 | [diff] [blame] | 91 | private: | 
|  | 92 | /// FunctionToStubMap - Keep track of the stub created for a particular | 
|  | 93 | /// function so that we can reuse them if necessary. | 
| Nick Lewycky | e2bcf13 | 2009-04-27 05:09:44 +0000 | [diff] [blame] | 94 | FunctionToStubMapTy FunctionToStubMap; | 
| Reid Spencer | ee44863 | 2005-07-12 15:51:55 +0000 | [diff] [blame] | 95 |  | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 96 | /// CallSiteToFunctionMap - Keep track of the function that each lazy call | 
|  | 97 | /// site corresponds to, and vice versa. | 
|  | 98 | CallSiteToFunctionMapTy CallSiteToFunctionMap; | 
|  | 99 | FunctionToCallSitesMapTy FunctionToCallSitesMap; | 
| Jeff Cohen | 00b16889 | 2005-07-27 06:12:32 +0000 | [diff] [blame] | 100 |  | 
| Evan Cheng | 5594f12 | 2008-11-10 01:52:24 +0000 | [diff] [blame] | 101 | /// GlobalToIndirectSymMap - Keep track of the indirect symbol created for a | 
| Evan Cheng | be8c03f | 2008-01-04 10:46:51 +0000 | [diff] [blame] | 102 | /// particular GlobalVariable so that we can reuse them if necessary. | 
| Nick Lewycky | e2bcf13 | 2009-04-27 05:09:44 +0000 | [diff] [blame] | 103 | GlobalToIndirectSymMapTy GlobalToIndirectSymMap; | 
| Evan Cheng | be8c03f | 2008-01-04 10:46:51 +0000 | [diff] [blame] | 104 |  | 
| Reid Spencer | ee44863 | 2005-07-12 15:51:55 +0000 | [diff] [blame] | 105 | public: | 
| Jeffrey Yasskin | 23e5fcf | 2009-10-23 22:37:43 +0000 | [diff] [blame] | 106 | JITResolverState() : FunctionToStubMap(this), | 
|  | 107 | FunctionToCallSitesMap(this) {} | 
|  | 108 |  | 
| Nick Lewycky | e2bcf13 | 2009-04-27 05:09:44 +0000 | [diff] [blame] | 109 | FunctionToStubMapTy& getFunctionToStubMap(const MutexGuard& locked) { | 
| Reid Spencer | ee44863 | 2005-07-12 15:51:55 +0000 | [diff] [blame] | 110 | assert(locked.holds(TheJIT->lock)); | 
|  | 111 | return FunctionToStubMap; | 
|  | 112 | } | 
| Jeff Cohen | 00b16889 | 2005-07-27 06:12:32 +0000 | [diff] [blame] | 113 |  | 
| Nick Lewycky | e2bcf13 | 2009-04-27 05:09:44 +0000 | [diff] [blame] | 114 | GlobalToIndirectSymMapTy& getGlobalToIndirectSymMap(const MutexGuard& locked) { | 
| Evan Cheng | be8c03f | 2008-01-04 10:46:51 +0000 | [diff] [blame] | 115 | assert(locked.holds(TheJIT->lock)); | 
| Evan Cheng | 5594f12 | 2008-11-10 01:52:24 +0000 | [diff] [blame] | 116 | return GlobalToIndirectSymMap; | 
| Evan Cheng | be8c03f | 2008-01-04 10:46:51 +0000 | [diff] [blame] | 117 | } | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 118 |  | 
|  | 119 | pair<void *, Function *> LookupFunctionFromCallSite( | 
|  | 120 | const MutexGuard &locked, void *CallSite) const { | 
|  | 121 | assert(locked.holds(TheJIT->lock)); | 
|  | 122 |  | 
|  | 123 | // The address given to us for the stub may not be exactly right, it might be | 
|  | 124 | // a little bit after the stub.  As such, use upper_bound to find it. | 
|  | 125 | CallSiteToFunctionMapTy::const_iterator I = | 
|  | 126 | CallSiteToFunctionMap.upper_bound(CallSite); | 
|  | 127 | assert(I != CallSiteToFunctionMap.begin() && | 
|  | 128 | "This is not a known call site!"); | 
|  | 129 | --I; | 
|  | 130 | return *I; | 
|  | 131 | } | 
|  | 132 |  | 
|  | 133 | void AddCallSite(const MutexGuard &locked, void *CallSite, Function *F) { | 
|  | 134 | assert(locked.holds(TheJIT->lock)); | 
|  | 135 |  | 
| Jeffrey Yasskin | 23e5fcf | 2009-10-23 22:37:43 +0000 | [diff] [blame] | 136 | bool Inserted = CallSiteToFunctionMap.insert( | 
|  | 137 | std::make_pair(CallSite, F)).second; | 
|  | 138 | (void)Inserted; | 
|  | 139 | assert(Inserted && "Pair was already in CallSiteToFunctionMap"); | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 140 | FunctionToCallSitesMap[F].insert(CallSite); | 
|  | 141 | } | 
|  | 142 |  | 
|  | 143 | // Returns the Function of the stub if a stub was erased, or NULL if there | 
|  | 144 | // was no stub.  This function uses the call-site->function map to find a | 
|  | 145 | // relevant function, but asserts that only stubs and not other call sites | 
|  | 146 | // will be passed in. | 
|  | 147 | Function *EraseStub(const MutexGuard &locked, void *Stub) { | 
|  | 148 | CallSiteToFunctionMapTy::iterator C2F_I = | 
|  | 149 | CallSiteToFunctionMap.find(Stub); | 
|  | 150 | if (C2F_I == CallSiteToFunctionMap.end()) { | 
|  | 151 | // Not a stub. | 
|  | 152 | return NULL; | 
|  | 153 | } | 
|  | 154 |  | 
|  | 155 | Function *const F = C2F_I->second; | 
|  | 156 | #ifndef NDEBUG | 
|  | 157 | void *RealStub = FunctionToStubMap.lookup(F); | 
|  | 158 | assert(RealStub == Stub && | 
|  | 159 | "Call-site that wasn't a stub pass in to EraseStub"); | 
|  | 160 | #endif | 
|  | 161 | FunctionToStubMap.erase(F); | 
|  | 162 | CallSiteToFunctionMap.erase(C2F_I); | 
|  | 163 |  | 
|  | 164 | // Remove the stub from the function->call-sites map, and remove the whole | 
|  | 165 | // entry from the map if that was the last call site. | 
|  | 166 | FunctionToCallSitesMapTy::iterator F2C_I = FunctionToCallSitesMap.find(F); | 
|  | 167 | assert(F2C_I != FunctionToCallSitesMap.end() && | 
|  | 168 | "FunctionToCallSitesMap broken"); | 
| Jeffrey Yasskin | 23e5fcf | 2009-10-23 22:37:43 +0000 | [diff] [blame] | 169 | bool Erased = F2C_I->second.erase(Stub); | 
|  | 170 | (void)Erased; | 
|  | 171 | assert(Erased && "FunctionToCallSitesMap broken"); | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 172 | if (F2C_I->second.empty()) | 
|  | 173 | FunctionToCallSitesMap.erase(F2C_I); | 
|  | 174 |  | 
|  | 175 | return F; | 
|  | 176 | } | 
|  | 177 |  | 
|  | 178 | void EraseAllCallSites(const MutexGuard &locked, Function *F) { | 
|  | 179 | assert(locked.holds(TheJIT->lock)); | 
| Jeffrey Yasskin | 23e5fcf | 2009-10-23 22:37:43 +0000 | [diff] [blame] | 180 | EraseAllCallSitesPrelocked(F); | 
|  | 181 | } | 
|  | 182 | void EraseAllCallSitesPrelocked(Function *F) { | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 183 | FunctionToCallSitesMapTy::iterator F2C = FunctionToCallSitesMap.find(F); | 
|  | 184 | if (F2C == FunctionToCallSitesMap.end()) | 
|  | 185 | return; | 
|  | 186 | for (SmallPtrSet<void*, 1>::const_iterator I = F2C->second.begin(), | 
|  | 187 | E = F2C->second.end(); I != E; ++I) { | 
| Jeffrey Yasskin | 23e5fcf | 2009-10-23 22:37:43 +0000 | [diff] [blame] | 188 | bool Erased = CallSiteToFunctionMap.erase(*I); | 
|  | 189 | (void)Erased; | 
|  | 190 | assert(Erased && "Missing call site->function mapping"); | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 191 | } | 
|  | 192 | FunctionToCallSitesMap.erase(F2C); | 
|  | 193 | } | 
| Reid Spencer | ee44863 | 2005-07-12 15:51:55 +0000 | [diff] [blame] | 194 | }; | 
| Jeff Cohen | 00b16889 | 2005-07-27 06:12:32 +0000 | [diff] [blame] | 195 |  | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 196 | /// JITResolver - Keep track of, and resolve, call sites for functions that | 
|  | 197 | /// have not yet been compiled. | 
|  | 198 | class JITResolver { | 
| Nick Lewycky | e2bcf13 | 2009-04-27 05:09:44 +0000 | [diff] [blame] | 199 | typedef JITResolverState::FunctionToStubMapTy FunctionToStubMapTy; | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 200 | typedef JITResolverState::CallSiteToFunctionMapTy CallSiteToFunctionMapTy; | 
| Nick Lewycky | e2bcf13 | 2009-04-27 05:09:44 +0000 | [diff] [blame] | 201 | typedef JITResolverState::GlobalToIndirectSymMapTy GlobalToIndirectSymMapTy; | 
|  | 202 |  | 
| Chris Lattner | 5e22558 | 2004-11-21 03:37:42 +0000 | [diff] [blame] | 203 | /// LazyResolverFn - The target lazy resolver function that we actually | 
|  | 204 | /// rewrite instructions to use. | 
|  | 205 | TargetJITInfo::LazyResolverFn LazyResolverFn; | 
|  | 206 |  | 
| Reid Spencer | ee44863 | 2005-07-12 15:51:55 +0000 | [diff] [blame] | 207 | JITResolverState state; | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 208 |  | 
| Chris Lattner | d91ff7c | 2005-04-18 01:44:27 +0000 | [diff] [blame] | 209 | /// ExternalFnToStubMap - This is the equivalent of FunctionToStubMap for | 
|  | 210 | /// external functions. | 
|  | 211 | std::map<void*, void*> ExternalFnToStubMap; | 
| Andrew Lenharth | 6a97461 | 2005-07-28 12:44:13 +0000 | [diff] [blame] | 212 |  | 
| Evan Cheng | 1606e8e | 2009-03-13 07:51:59 +0000 | [diff] [blame] | 213 | /// revGOTMap - map addresses to indexes in the GOT | 
| Andrew Lenharth | 6a97461 | 2005-07-28 12:44:13 +0000 | [diff] [blame] | 214 | std::map<void*, unsigned> revGOTMap; | 
|  | 215 | unsigned nextGOTIndex; | 
|  | 216 |  | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 217 | JITEmitter &JE; | 
|  | 218 |  | 
| Chris Lattner | e748401 | 2007-02-24 02:57:03 +0000 | [diff] [blame] | 219 | static JITResolver *TheJITResolver; | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 220 | public: | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 221 | explicit JITResolver(JIT &jit, JITEmitter &je) : nextGOTIndex(0), JE(je) { | 
| Chris Lattner | e748401 | 2007-02-24 02:57:03 +0000 | [diff] [blame] | 222 | TheJIT = &jit; | 
|  | 223 |  | 
|  | 224 | LazyResolverFn = jit.getJITInfo().getLazyResolverFunction(JITCompilerFn); | 
|  | 225 | assert(TheJITResolver == 0 && "Multiple JIT resolvers?"); | 
|  | 226 | TheJITResolver = this; | 
|  | 227 | } | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 228 |  | 
| Chris Lattner | e748401 | 2007-02-24 02:57:03 +0000 | [diff] [blame] | 229 | ~JITResolver() { | 
|  | 230 | TheJITResolver = 0; | 
| Chris Lattner | 5e22558 | 2004-11-21 03:37:42 +0000 | [diff] [blame] | 231 | } | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 232 |  | 
| Evan Cheng | 704bff9 | 2008-11-13 21:50:50 +0000 | [diff] [blame] | 233 | /// getFunctionStubIfAvailable - This returns a pointer to a function stub | 
|  | 234 | /// if it has already been created. | 
|  | 235 | void *getFunctionStubIfAvailable(Function *F); | 
|  | 236 |  | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 237 | /// getFunctionStub - This returns a pointer to a function stub, creating | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 238 | /// one on demand as needed.  If empty is true, create a function stub | 
|  | 239 | /// pointing at address 0, to be filled in later. | 
| Nate Begeman | b9c6c9b | 2009-03-07 06:41:19 +0000 | [diff] [blame] | 240 | void *getFunctionStub(Function *F); | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 241 |  | 
| Chris Lattner | d91ff7c | 2005-04-18 01:44:27 +0000 | [diff] [blame] | 242 | /// getExternalFunctionStub - Return a stub for the function at the | 
|  | 243 | /// specified address, created lazily on demand. | 
|  | 244 | void *getExternalFunctionStub(void *FnAddr); | 
|  | 245 |  | 
| Evan Cheng | 5594f12 | 2008-11-10 01:52:24 +0000 | [diff] [blame] | 246 | /// getGlobalValueIndirectSym - Return an indirect symbol containing the | 
| Evan Cheng | c96a8e7 | 2008-11-05 01:50:32 +0000 | [diff] [blame] | 247 | /// specified GV address. | 
| Evan Cheng | 5594f12 | 2008-11-10 01:52:24 +0000 | [diff] [blame] | 248 | void *getGlobalValueIndirectSym(GlobalValue *V, void *GVAddress); | 
| Evan Cheng | be8c03f | 2008-01-04 10:46:51 +0000 | [diff] [blame] | 249 |  | 
| Chris Lattner | 5e22558 | 2004-11-21 03:37:42 +0000 | [diff] [blame] | 250 | /// AddCallbackAtLocation - If the target is capable of rewriting an | 
|  | 251 | /// instruction without the use of a stub, record the location of the use so | 
|  | 252 | /// we know which function is being used at the location. | 
|  | 253 | void *AddCallbackAtLocation(Function *F, void *Location) { | 
| Reid Spencer | ee44863 | 2005-07-12 15:51:55 +0000 | [diff] [blame] | 254 | MutexGuard locked(TheJIT->lock); | 
| Chris Lattner | 5e22558 | 2004-11-21 03:37:42 +0000 | [diff] [blame] | 255 | /// Get the target-specific JIT resolver function. | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 256 | state.AddCallSite(locked, Location, F); | 
| Chris Lattner | 870286a | 2006-06-01 17:29:22 +0000 | [diff] [blame] | 257 | return (void*)(intptr_t)LazyResolverFn; | 
| Chris Lattner | 5e22558 | 2004-11-21 03:37:42 +0000 | [diff] [blame] | 258 | } | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 259 |  | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 260 | void getRelocatableGVs(SmallVectorImpl<GlobalValue*> &GVs, | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 261 | SmallVectorImpl<void*> &Ptrs); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 262 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 263 | GlobalValue *invalidateStub(void *Stub); | 
| Chris Lattner | 5e22558 | 2004-11-21 03:37:42 +0000 | [diff] [blame] | 264 |  | 
| Andrew Lenharth | 6a97461 | 2005-07-28 12:44:13 +0000 | [diff] [blame] | 265 | /// getGOTIndexForAddress - Return a new or existing index in the GOT for | 
| Chris Lattner | 8907b4b | 2007-12-05 23:39:57 +0000 | [diff] [blame] | 266 | /// an address.  This function only manages slots, it does not manage the | 
| Andrew Lenharth | 6a97461 | 2005-07-28 12:44:13 +0000 | [diff] [blame] | 267 | /// contents of the slots or the memory associated with the GOT. | 
| Chris Lattner | 8907b4b | 2007-12-05 23:39:57 +0000 | [diff] [blame] | 268 | unsigned getGOTIndexForAddr(void *addr); | 
| Andrew Lenharth | 6a97461 | 2005-07-28 12:44:13 +0000 | [diff] [blame] | 269 |  | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 270 | /// JITCompilerFn - This function is called to resolve a stub to a compiled | 
|  | 271 | /// address.  If the LLVM Function corresponding to the stub has not yet | 
|  | 272 | /// been compiled, this function compiles it first. | 
|  | 273 | static void *JITCompilerFn(void *Stub); | 
|  | 274 | }; | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 275 |  | 
|  | 276 | /// JITEmitter - The JIT implementation of the MachineCodeEmitter, which is | 
|  | 277 | /// used to output functions to memory for execution. | 
|  | 278 | class JITEmitter : public JITCodeEmitter { | 
|  | 279 | JITMemoryManager *MemMgr; | 
|  | 280 |  | 
|  | 281 | // When outputting a function stub in the context of some other function, we | 
|  | 282 | // save BufferBegin/BufferEnd/CurBufferPtr here. | 
|  | 283 | uint8_t *SavedBufferBegin, *SavedBufferEnd, *SavedCurBufferPtr; | 
|  | 284 |  | 
|  | 285 | // When reattempting to JIT a function after running out of space, we store | 
|  | 286 | // the estimated size of the function we're trying to JIT here, so we can | 
|  | 287 | // ask the memory manager for at least this much space.  When we | 
|  | 288 | // successfully emit the function, we reset this back to zero. | 
|  | 289 | uintptr_t SizeEstimate; | 
|  | 290 |  | 
|  | 291 | /// Relocations - These are the relocations that the function needs, as | 
|  | 292 | /// emitted. | 
|  | 293 | std::vector<MachineRelocation> Relocations; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 294 |  | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 295 | /// MBBLocations - This vector is a mapping from MBB ID's to their address. | 
|  | 296 | /// It is filled in by the StartMachineBasicBlock callback and queried by | 
|  | 297 | /// the getMachineBasicBlockAddress callback. | 
|  | 298 | std::vector<uintptr_t> MBBLocations; | 
|  | 299 |  | 
|  | 300 | /// ConstantPool - The constant pool for the current function. | 
|  | 301 | /// | 
|  | 302 | MachineConstantPool *ConstantPool; | 
|  | 303 |  | 
|  | 304 | /// ConstantPoolBase - A pointer to the first entry in the constant pool. | 
|  | 305 | /// | 
|  | 306 | void *ConstantPoolBase; | 
|  | 307 |  | 
|  | 308 | /// ConstPoolAddresses - Addresses of individual constant pool entries. | 
|  | 309 | /// | 
|  | 310 | SmallVector<uintptr_t, 8> ConstPoolAddresses; | 
|  | 311 |  | 
|  | 312 | /// JumpTable - The jump tables for the current function. | 
|  | 313 | /// | 
|  | 314 | MachineJumpTableInfo *JumpTable; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 315 |  | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 316 | /// JumpTableBase - A pointer to the first entry in the jump table. | 
|  | 317 | /// | 
|  | 318 | void *JumpTableBase; | 
|  | 319 |  | 
|  | 320 | /// Resolver - This contains info about the currently resolved functions. | 
|  | 321 | JITResolver Resolver; | 
|  | 322 |  | 
|  | 323 | /// DE - The dwarf emitter for the jit. | 
|  | 324 | OwningPtr<JITDwarfEmitter> DE; | 
|  | 325 |  | 
|  | 326 | /// DR - The debug registerer for the jit. | 
|  | 327 | OwningPtr<JITDebugRegisterer> DR; | 
|  | 328 |  | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 329 | /// LabelLocations - This vector is a mapping from Label ID's to their | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 330 | /// address. | 
|  | 331 | std::vector<uintptr_t> LabelLocations; | 
|  | 332 |  | 
|  | 333 | /// MMI - Machine module info for exception informations | 
|  | 334 | MachineModuleInfo* MMI; | 
|  | 335 |  | 
|  | 336 | // GVSet - a set to keep track of which globals have been seen | 
|  | 337 | SmallPtrSet<const GlobalVariable*, 8> GVSet; | 
|  | 338 |  | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 339 | // CurFn - The llvm function being emitted.  Only valid during | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 340 | // finishFunction(). | 
|  | 341 | const Function *CurFn; | 
|  | 342 |  | 
|  | 343 | /// Information about emitted code, which is passed to the | 
|  | 344 | /// JITEventListeners.  This is reset in startFunction and used in | 
|  | 345 | /// finishFunction. | 
|  | 346 | JITEvent_EmittedFunctionDetails EmissionDetails; | 
|  | 347 |  | 
|  | 348 | struct EmittedCode { | 
|  | 349 | void *FunctionBody;  // Beginning of the function's allocation. | 
|  | 350 | void *Code;  // The address the function's code actually starts at. | 
|  | 351 | void *ExceptionTable; | 
|  | 352 | EmittedCode() : FunctionBody(0), Code(0), ExceptionTable(0) {} | 
|  | 353 | }; | 
|  | 354 | struct EmittedFunctionConfig : public ValueMapConfig<const Function*> { | 
|  | 355 | typedef JITEmitter *ExtraData; | 
|  | 356 | static void onDelete(JITEmitter *, const Function*); | 
|  | 357 | static void onRAUW(JITEmitter *, const Function*, const Function*); | 
|  | 358 | }; | 
|  | 359 | ValueMap<const Function *, EmittedCode, | 
|  | 360 | EmittedFunctionConfig> EmittedFunctions; | 
|  | 361 |  | 
|  | 362 | // CurFnStubUses - For a given Function, a vector of stubs that it | 
|  | 363 | // references.  This facilitates the JIT detecting that a stub is no | 
|  | 364 | // longer used, so that it may be deallocated. | 
|  | 365 | DenseMap<AssertingVH<const Function>, SmallVector<void*, 1> > CurFnStubUses; | 
|  | 366 |  | 
|  | 367 | // StubFnRefs - For a given pointer to a stub, a set of Functions which | 
|  | 368 | // reference the stub.  When the count of a stub's references drops to zero, | 
|  | 369 | // the stub is unused. | 
|  | 370 | DenseMap<void *, SmallPtrSet<const Function*, 1> > StubFnRefs; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 371 |  | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 372 | DebugLocTuple PrevDLT; | 
|  | 373 |  | 
|  | 374 | public: | 
|  | 375 | JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM) | 
|  | 376 | : SizeEstimate(0), Resolver(jit, *this), MMI(0), CurFn(0), | 
|  | 377 | EmittedFunctions(this) { | 
|  | 378 | MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager(); | 
|  | 379 | if (jit.getJITInfo().needsGOT()) { | 
|  | 380 | MemMgr->AllocateGOT(); | 
|  | 381 | DEBUG(errs() << "JIT is managing a GOT\n"); | 
|  | 382 | } | 
|  | 383 |  | 
|  | 384 | if (DwarfExceptionHandling || JITEmitDebugInfo) { | 
|  | 385 | DE.reset(new JITDwarfEmitter(jit)); | 
|  | 386 | } | 
|  | 387 | if (JITEmitDebugInfo) { | 
|  | 388 | DR.reset(new JITDebugRegisterer(TM)); | 
|  | 389 | } | 
|  | 390 | } | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 391 | ~JITEmitter() { | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 392 | delete MemMgr; | 
|  | 393 | } | 
|  | 394 |  | 
|  | 395 | /// classof - Methods for support type inquiry through isa, cast, and | 
|  | 396 | /// dyn_cast: | 
|  | 397 | /// | 
|  | 398 | static inline bool classof(const JITEmitter*) { return true; } | 
|  | 399 | static inline bool classof(const MachineCodeEmitter*) { return true; } | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 400 |  | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 401 | JITResolver &getJITResolver() { return Resolver; } | 
|  | 402 |  | 
|  | 403 | virtual void startFunction(MachineFunction &F); | 
|  | 404 | virtual bool finishFunction(MachineFunction &F); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 405 |  | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 406 | void emitConstantPool(MachineConstantPool *MCP); | 
|  | 407 | void initJumpTableInfo(MachineJumpTableInfo *MJTI); | 
|  | 408 | void emitJumpTableInfo(MachineJumpTableInfo *MJTI); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 409 |  | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 410 | virtual void startGVStub(const GlobalValue* GV, unsigned StubSize, | 
|  | 411 | unsigned Alignment = 1); | 
|  | 412 | virtual void startGVStub(const GlobalValue* GV, void *Buffer, | 
|  | 413 | unsigned StubSize); | 
|  | 414 | virtual void* finishGVStub(const GlobalValue *GV); | 
|  | 415 |  | 
|  | 416 | /// allocateSpace - Reserves space in the current block if any, or | 
|  | 417 | /// allocate a new one of the given size. | 
|  | 418 | virtual void *allocateSpace(uintptr_t Size, unsigned Alignment); | 
|  | 419 |  | 
|  | 420 | /// allocateGlobal - Allocate memory for a global.  Unlike allocateSpace, | 
|  | 421 | /// this method does not allocate memory in the current output buffer, | 
|  | 422 | /// because a global may live longer than the current function. | 
|  | 423 | virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment); | 
|  | 424 |  | 
|  | 425 | virtual void addRelocation(const MachineRelocation &MR) { | 
|  | 426 | Relocations.push_back(MR); | 
|  | 427 | } | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 428 |  | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 429 | virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { | 
|  | 430 | if (MBBLocations.size() <= (unsigned)MBB->getNumber()) | 
|  | 431 | MBBLocations.resize((MBB->getNumber()+1)*2); | 
|  | 432 | MBBLocations[MBB->getNumber()] = getCurrentPCValue(); | 
|  | 433 | DEBUG(errs() << "JIT: Emitting BB" << MBB->getNumber() << " at [" | 
|  | 434 | << (void*) getCurrentPCValue() << "]\n"); | 
|  | 435 | } | 
|  | 436 |  | 
|  | 437 | virtual uintptr_t getConstantPoolEntryAddress(unsigned Entry) const; | 
|  | 438 | virtual uintptr_t getJumpTableEntryAddress(unsigned Entry) const; | 
|  | 439 |  | 
|  | 440 | virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 441 | assert(MBBLocations.size() > (unsigned)MBB->getNumber() && | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 442 | MBBLocations[MBB->getNumber()] && "MBB not emitted!"); | 
|  | 443 | return MBBLocations[MBB->getNumber()]; | 
|  | 444 | } | 
|  | 445 |  | 
|  | 446 | /// retryWithMoreMemory - Log a retry and deallocate all memory for the | 
|  | 447 | /// given function.  Increase the minimum allocation size so that we get | 
|  | 448 | /// more memory next time. | 
|  | 449 | void retryWithMoreMemory(MachineFunction &F); | 
|  | 450 |  | 
|  | 451 | /// deallocateMemForFunction - Deallocate all memory for the specified | 
|  | 452 | /// function body. | 
|  | 453 | void deallocateMemForFunction(const Function *F); | 
|  | 454 |  | 
|  | 455 | /// AddStubToCurrentFunction - Mark the current function being JIT'd as | 
|  | 456 | /// using the stub at the specified address. Allows | 
|  | 457 | /// deallocateMemForFunction to also remove stubs no longer referenced. | 
|  | 458 | void AddStubToCurrentFunction(void *Stub); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 459 |  | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 460 | virtual void processDebugLoc(DebugLoc DL, bool BeforePrintingInsn); | 
|  | 461 |  | 
|  | 462 | virtual void emitLabel(uint64_t LabelID) { | 
|  | 463 | if (LabelLocations.size() <= LabelID) | 
|  | 464 | LabelLocations.resize((LabelID+1)*2); | 
|  | 465 | LabelLocations[LabelID] = getCurrentPCValue(); | 
|  | 466 | } | 
|  | 467 |  | 
|  | 468 | virtual uintptr_t getLabelAddress(uint64_t LabelID) const { | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 469 | assert(LabelLocations.size() > (unsigned)LabelID && | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 470 | LabelLocations[LabelID] && "Label not emitted!"); | 
|  | 471 | return LabelLocations[LabelID]; | 
|  | 472 | } | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 473 |  | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 474 | virtual void setModuleInfo(MachineModuleInfo* Info) { | 
|  | 475 | MMI = Info; | 
|  | 476 | if (DE.get()) DE->setModuleInfo(Info); | 
|  | 477 | } | 
|  | 478 |  | 
|  | 479 | void setMemoryExecutable() { | 
|  | 480 | MemMgr->setMemoryExecutable(); | 
|  | 481 | } | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 482 |  | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 483 | JITMemoryManager *getMemMgr() const { return MemMgr; } | 
|  | 484 |  | 
|  | 485 | private: | 
| Jeffrey Yasskin | 2d27441 | 2009-11-07 08:51:52 +0000 | [diff] [blame] | 486 | void *getPointerToGlobal(GlobalValue *GV, void *Reference, | 
|  | 487 | bool MayNeedFarStub); | 
|  | 488 | void *getPointerToGVIndirectSym(GlobalValue *V, void *Reference); | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 489 | unsigned addSizeOfGlobal(const GlobalVariable *GV, unsigned Size); | 
|  | 490 | unsigned addSizeOfGlobalsInConstantVal(const Constant *C, unsigned Size); | 
|  | 491 | unsigned addSizeOfGlobalsInInitializer(const Constant *Init, unsigned Size); | 
|  | 492 | unsigned GetSizeOfGlobalsInBytes(MachineFunction &MF); | 
|  | 493 | }; | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 494 | } | 
|  | 495 |  | 
| Chris Lattner | e748401 | 2007-02-24 02:57:03 +0000 | [diff] [blame] | 496 | JITResolver *JITResolver::TheJITResolver = 0; | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 497 |  | 
| Jeffrey Yasskin | 23e5fcf | 2009-10-23 22:37:43 +0000 | [diff] [blame] | 498 | void CallSiteValueMapConfig::onDelete(JITResolverState *JRS, Function *F) { | 
|  | 499 | JRS->EraseAllCallSitesPrelocked(F); | 
|  | 500 | } | 
|  | 501 |  | 
| Evan Cheng | 704bff9 | 2008-11-13 21:50:50 +0000 | [diff] [blame] | 502 | /// getFunctionStubIfAvailable - This returns a pointer to a function stub | 
|  | 503 | /// if it has already been created. | 
|  | 504 | void *JITResolver::getFunctionStubIfAvailable(Function *F) { | 
|  | 505 | MutexGuard locked(TheJIT->lock); | 
|  | 506 |  | 
|  | 507 | // If we already have a stub for this function, recycle it. | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 508 | return state.getFunctionToStubMap(locked).lookup(F); | 
| Evan Cheng | 704bff9 | 2008-11-13 21:50:50 +0000 | [diff] [blame] | 509 | } | 
|  | 510 |  | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 511 | /// getFunctionStub - This returns a pointer to a function stub, creating | 
|  | 512 | /// one on demand as needed. | 
| Nate Begeman | b9c6c9b | 2009-03-07 06:41:19 +0000 | [diff] [blame] | 513 | void *JITResolver::getFunctionStub(Function *F) { | 
| Reid Spencer | ee44863 | 2005-07-12 15:51:55 +0000 | [diff] [blame] | 514 | MutexGuard locked(TheJIT->lock); | 
|  | 515 |  | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 516 | // If we already have a stub for this function, recycle it. | 
| Reid Spencer | ee44863 | 2005-07-12 15:51:55 +0000 | [diff] [blame] | 517 | void *&Stub = state.getFunctionToStubMap(locked)[F]; | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 518 | if (Stub) return Stub; | 
|  | 519 |  | 
| Jeffrey Yasskin | dc85724 | 2009-10-27 20:30:28 +0000 | [diff] [blame] | 520 | // Call the lazy resolver function if we are JIT'ing lazily.  Otherwise we | 
|  | 521 | // must resolve the symbol now. | 
|  | 522 | void *Actual = TheJIT->isCompilingLazily() | 
|  | 523 | ? (void *)(intptr_t)LazyResolverFn : (void *)0; | 
|  | 524 |  | 
| Nate Begeman | b9c6c9b | 2009-03-07 06:41:19 +0000 | [diff] [blame] | 525 | // If this is an external declaration, attempt to resolve the address now | 
|  | 526 | // to place in the stub. | 
| Dan Gohman | 69f9378 | 2009-01-05 05:32:42 +0000 | [diff] [blame] | 527 | if (F->isDeclaration() && !F->hasNotBeenReadFromBitcode()) { | 
| Chris Lattner | b43dbdc | 2004-11-22 07:24:43 +0000 | [diff] [blame] | 528 | Actual = TheJIT->getPointerToFunction(F); | 
| Misha Brukman | f976c85 | 2005-04-21 22:55:34 +0000 | [diff] [blame] | 529 |  | 
| Dan Gohman | 69f9378 | 2009-01-05 05:32:42 +0000 | [diff] [blame] | 530 | // If we resolved the symbol to a null address (eg. a weak external) | 
| Jeffrey Yasskin | 6f348e4 | 2009-11-09 22:34:19 +0000 | [diff] [blame] | 531 | // don't emit a stub. Return a null pointer to the application. | 
|  | 532 | if (!Actual) return 0; | 
| Dan Gohman | 69f9378 | 2009-01-05 05:32:42 +0000 | [diff] [blame] | 533 | } | 
|  | 534 |  | 
| Nate Begeman | b9c6c9b | 2009-03-07 06:41:19 +0000 | [diff] [blame] | 535 | // Codegen a new stub, calling the lazy resolver or the actual address of the | 
|  | 536 | // external function, if it was resolved. | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 537 | Stub = TheJIT->getJITInfo().emitFunctionStub(F, Actual, JE); | 
| Chris Lattner | b43dbdc | 2004-11-22 07:24:43 +0000 | [diff] [blame] | 538 |  | 
| Chris Lattner | 870286a | 2006-06-01 17:29:22 +0000 | [diff] [blame] | 539 | if (Actual != (void*)(intptr_t)LazyResolverFn) { | 
| Chris Lattner | b43dbdc | 2004-11-22 07:24:43 +0000 | [diff] [blame] | 540 | // If we are getting the stub for an external function, we really want the | 
|  | 541 | // address of the stub in the GlobalAddressMap for the JIT, not the address | 
|  | 542 | // of the external function. | 
|  | 543 | TheJIT->updateGlobalMapping(F, Stub); | 
|  | 544 | } | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 545 |  | 
| Daniel Dunbar | ce63ffb | 2009-07-25 00:23:56 +0000 | [diff] [blame] | 546 | DEBUG(errs() << "JIT: Stub emitted at [" << Stub << "] for function '" | 
|  | 547 | << F->getName() << "'\n"); | 
| Chris Lattner | cb47941 | 2004-11-21 03:44:32 +0000 | [diff] [blame] | 548 |  | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 549 | // Finally, keep track of the stub-to-Function mapping so that the | 
|  | 550 | // JITCompilerFn knows which function to compile! | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 551 | state.AddCallSite(locked, Stub, F); | 
| Jeffrey Yasskin | e5f8798 | 2009-10-13 21:32:57 +0000 | [diff] [blame] | 552 |  | 
| Nate Begeman | b9c6c9b | 2009-03-07 06:41:19 +0000 | [diff] [blame] | 553 | // If we are JIT'ing non-lazily but need to call a function that does not | 
|  | 554 | // exist yet, add it to the JIT's work list so that we can fill in the stub | 
|  | 555 | // address later. | 
| Jeffrey Yasskin | dc85724 | 2009-10-27 20:30:28 +0000 | [diff] [blame] | 556 | if (!Actual && !TheJIT->isCompilingLazily()) | 
| Nate Begeman | b9c6c9b | 2009-03-07 06:41:19 +0000 | [diff] [blame] | 557 | if (!F->isDeclaration() || F->hasNotBeenReadFromBitcode()) | 
|  | 558 | TheJIT->addPendingFunction(F); | 
| Jeffrey Yasskin | e5f8798 | 2009-10-13 21:32:57 +0000 | [diff] [blame] | 559 |  | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 560 | return Stub; | 
|  | 561 | } | 
|  | 562 |  | 
| Evan Cheng | 5594f12 | 2008-11-10 01:52:24 +0000 | [diff] [blame] | 563 | /// getGlobalValueIndirectSym - Return a lazy pointer containing the specified | 
| Evan Cheng | be8c03f | 2008-01-04 10:46:51 +0000 | [diff] [blame] | 564 | /// GV address. | 
| Evan Cheng | 5594f12 | 2008-11-10 01:52:24 +0000 | [diff] [blame] | 565 | void *JITResolver::getGlobalValueIndirectSym(GlobalValue *GV, void *GVAddress) { | 
| Evan Cheng | be8c03f | 2008-01-04 10:46:51 +0000 | [diff] [blame] | 566 | MutexGuard locked(TheJIT->lock); | 
|  | 567 |  | 
|  | 568 | // If we already have a stub for this global variable, recycle it. | 
| Evan Cheng | 5594f12 | 2008-11-10 01:52:24 +0000 | [diff] [blame] | 569 | void *&IndirectSym = state.getGlobalToIndirectSymMap(locked)[GV]; | 
|  | 570 | if (IndirectSym) return IndirectSym; | 
| Evan Cheng | be8c03f | 2008-01-04 10:46:51 +0000 | [diff] [blame] | 571 |  | 
| Evan Cheng | e4d783d | 2008-11-10 23:26:16 +0000 | [diff] [blame] | 572 | // Otherwise, codegen a new indirect symbol. | 
| Evan Cheng | 5594f12 | 2008-11-10 01:52:24 +0000 | [diff] [blame] | 573 | IndirectSym = TheJIT->getJITInfo().emitGlobalValueIndirectSym(GV, GVAddress, | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 574 | JE); | 
| Evan Cheng | be8c03f | 2008-01-04 10:46:51 +0000 | [diff] [blame] | 575 |  | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 576 | DEBUG(errs() << "JIT: Indirect symbol emitted at [" << IndirectSym | 
| Daniel Dunbar | ce63ffb | 2009-07-25 00:23:56 +0000 | [diff] [blame] | 577 | << "] for GV '" << GV->getName() << "'\n"); | 
| Evan Cheng | be8c03f | 2008-01-04 10:46:51 +0000 | [diff] [blame] | 578 |  | 
| Evan Cheng | 5594f12 | 2008-11-10 01:52:24 +0000 | [diff] [blame] | 579 | return IndirectSym; | 
| Evan Cheng | be8c03f | 2008-01-04 10:46:51 +0000 | [diff] [blame] | 580 | } | 
|  | 581 |  | 
| Chris Lattner | d91ff7c | 2005-04-18 01:44:27 +0000 | [diff] [blame] | 582 | /// getExternalFunctionStub - Return a stub for the function at the | 
|  | 583 | /// specified address, created lazily on demand. | 
|  | 584 | void *JITResolver::getExternalFunctionStub(void *FnAddr) { | 
|  | 585 | // If we already have a stub for this function, recycle it. | 
|  | 586 | void *&Stub = ExternalFnToStubMap[FnAddr]; | 
|  | 587 | if (Stub) return Stub; | 
|  | 588 |  | 
| Jeffrey Yasskin | e637c19 | 2009-11-07 00:00:10 +0000 | [diff] [blame] | 589 | Stub = TheJIT->getJITInfo().emitFunctionStub(0, FnAddr, JE); | 
| Evan Cheng | 55fc280 | 2006-07-25 20:40:54 +0000 | [diff] [blame] | 590 |  | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 591 | DEBUG(errs() << "JIT: Stub emitted at [" << Stub | 
|  | 592 | << "] for external function at '" << FnAddr << "'\n"); | 
| Chris Lattner | d91ff7c | 2005-04-18 01:44:27 +0000 | [diff] [blame] | 593 | return Stub; | 
|  | 594 | } | 
|  | 595 |  | 
| Andrew Lenharth | 6a97461 | 2005-07-28 12:44:13 +0000 | [diff] [blame] | 596 | unsigned JITResolver::getGOTIndexForAddr(void* addr) { | 
|  | 597 | unsigned idx = revGOTMap[addr]; | 
|  | 598 | if (!idx) { | 
|  | 599 | idx = ++nextGOTIndex; | 
|  | 600 | revGOTMap[addr] = idx; | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 601 | DEBUG(errs() << "JIT: Adding GOT entry " << idx << " for addr [" | 
|  | 602 | << addr << "]\n"); | 
| Andrew Lenharth | 6a97461 | 2005-07-28 12:44:13 +0000 | [diff] [blame] | 603 | } | 
|  | 604 | return idx; | 
|  | 605 | } | 
| Chris Lattner | d91ff7c | 2005-04-18 01:44:27 +0000 | [diff] [blame] | 606 |  | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 607 | void JITResolver::getRelocatableGVs(SmallVectorImpl<GlobalValue*> &GVs, | 
|  | 608 | SmallVectorImpl<void*> &Ptrs) { | 
|  | 609 | MutexGuard locked(TheJIT->lock); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 610 |  | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 611 | const FunctionToStubMapTy &FM = state.getFunctionToStubMap(locked); | 
| Nick Lewycky | e2bcf13 | 2009-04-27 05:09:44 +0000 | [diff] [blame] | 612 | GlobalToIndirectSymMapTy &GM = state.getGlobalToIndirectSymMap(locked); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 613 |  | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 614 | for (FunctionToStubMapTy::const_iterator i = FM.begin(), e = FM.end(); | 
|  | 615 | i != e; ++i){ | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 616 | Function *F = i->first; | 
|  | 617 | if (F->isDeclaration() && F->hasExternalLinkage()) { | 
|  | 618 | GVs.push_back(i->first); | 
|  | 619 | Ptrs.push_back(i->second); | 
|  | 620 | } | 
|  | 621 | } | 
| Nick Lewycky | e2bcf13 | 2009-04-27 05:09:44 +0000 | [diff] [blame] | 622 | for (GlobalToIndirectSymMapTy::iterator i = GM.begin(), e = GM.end(); | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 623 | i != e; ++i) { | 
|  | 624 | GVs.push_back(i->first); | 
|  | 625 | Ptrs.push_back(i->second); | 
|  | 626 | } | 
|  | 627 | } | 
|  | 628 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 629 | GlobalValue *JITResolver::invalidateStub(void *Stub) { | 
|  | 630 | MutexGuard locked(TheJIT->lock); | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 631 |  | 
| Nick Lewycky | e2bcf13 | 2009-04-27 05:09:44 +0000 | [diff] [blame] | 632 | GlobalToIndirectSymMapTy &GM = state.getGlobalToIndirectSymMap(locked); | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 633 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 634 | // Look up the cheap way first, to see if it's a function stub we are | 
|  | 635 | // invalidating.  If so, remove it from both the forward and reverse maps. | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 636 | if (Function *F = state.EraseStub(locked, Stub)) { | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 637 | return F; | 
|  | 638 | } | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 639 |  | 
| Nate Begeman | 841c6a4 | 2009-03-11 07:03:43 +0000 | [diff] [blame] | 640 | // Otherwise, it might be an indirect symbol stub.  Find it and remove it. | 
| Nick Lewycky | e2bcf13 | 2009-04-27 05:09:44 +0000 | [diff] [blame] | 641 | for (GlobalToIndirectSymMapTy::iterator i = GM.begin(), e = GM.end(); | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 642 | i != e; ++i) { | 
|  | 643 | if (i->second != Stub) | 
|  | 644 | continue; | 
|  | 645 | GlobalValue *GV = i->first; | 
|  | 646 | GM.erase(i); | 
|  | 647 | return GV; | 
|  | 648 | } | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 649 |  | 
| Nate Begeman | 841c6a4 | 2009-03-11 07:03:43 +0000 | [diff] [blame] | 650 | // Lastly, check to see if it's in the ExternalFnToStubMap. | 
|  | 651 | for (std::map<void *, void *>::iterator i = ExternalFnToStubMap.begin(), | 
|  | 652 | e = ExternalFnToStubMap.end(); i != e; ++i) { | 
|  | 653 | if (i->second != Stub) | 
|  | 654 | continue; | 
|  | 655 | ExternalFnToStubMap.erase(i); | 
|  | 656 | break; | 
|  | 657 | } | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 658 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 659 | return 0; | 
|  | 660 | } | 
|  | 661 |  | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 662 | /// JITCompilerFn - This function is called when a lazy compilation stub has | 
|  | 663 | /// been entered.  It looks up which function this stub corresponds to, compiles | 
|  | 664 | /// it if necessary, then returns the resultant function pointer. | 
|  | 665 | void *JITResolver::JITCompilerFn(void *Stub) { | 
| Chris Lattner | e748401 | 2007-02-24 02:57:03 +0000 | [diff] [blame] | 666 | JITResolver &JR = *TheJITResolver; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 667 |  | 
| Nicolas Geoffray | dcb31e1 | 2008-10-03 07:27:08 +0000 | [diff] [blame] | 668 | Function* F = 0; | 
|  | 669 | void* ActualPtr = 0; | 
| Misha Brukman | f976c85 | 2005-04-21 22:55:34 +0000 | [diff] [blame] | 670 |  | 
| Nicolas Geoffray | dcb31e1 | 2008-10-03 07:27:08 +0000 | [diff] [blame] | 671 | { | 
|  | 672 | // Only lock for getting the Function. The call getPointerToFunction made | 
|  | 673 | // in this function might trigger function materializing, which requires | 
|  | 674 | // JIT lock to be unlocked. | 
|  | 675 | MutexGuard locked(TheJIT->lock); | 
| Reid Spencer | ee44863 | 2005-07-12 15:51:55 +0000 | [diff] [blame] | 676 |  | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 677 | // The address given to us for the stub may not be exactly right, it might | 
|  | 678 | // be a little bit after the stub.  As such, use upper_bound to find it. | 
|  | 679 | pair<void*, Function*> I = | 
|  | 680 | JR.state.LookupFunctionFromCallSite(locked, Stub); | 
|  | 681 | F = I.second; | 
|  | 682 | ActualPtr = I.first; | 
| Nicolas Geoffray | dcb31e1 | 2008-10-03 07:27:08 +0000 | [diff] [blame] | 683 | } | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 684 |  | 
| Evan Cheng | 9da60f9 | 2007-06-30 00:10:37 +0000 | [diff] [blame] | 685 | // If we have already code generated the function, just return the address. | 
|  | 686 | void *Result = TheJIT->getPointerToGlobalIfAvailable(F); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 687 |  | 
| Evan Cheng | 9da60f9 | 2007-06-30 00:10:37 +0000 | [diff] [blame] | 688 | if (!Result) { | 
|  | 689 | // Otherwise we don't have it, do lazy compilation now. | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 690 |  | 
| Evan Cheng | 9da60f9 | 2007-06-30 00:10:37 +0000 | [diff] [blame] | 691 | // If lazy compilation is disabled, emit a useful error message and abort. | 
| Jeffrey Yasskin | dc85724 | 2009-10-27 20:30:28 +0000 | [diff] [blame] | 692 | if (!TheJIT->isCompilingLazily()) { | 
| Torok Edwin | 7d696d8 | 2009-07-11 13:10:19 +0000 | [diff] [blame] | 693 | llvm_report_error("LLVM JIT requested to do lazy compilation of function '" | 
|  | 694 | + F->getName() + "' when lazy compiles are disabled!"); | 
| Evan Cheng | 9da60f9 | 2007-06-30 00:10:37 +0000 | [diff] [blame] | 695 | } | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 696 |  | 
| Daniel Dunbar | ce63ffb | 2009-07-25 00:23:56 +0000 | [diff] [blame] | 697 | DEBUG(errs() << "JIT: Lazily resolving function '" << F->getName() | 
|  | 698 | << "' In stub ptr = " << Stub << " actual ptr = " | 
|  | 699 | << ActualPtr << "\n"); | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 700 |  | 
| Evan Cheng | 9da60f9 | 2007-06-30 00:10:37 +0000 | [diff] [blame] | 701 | Result = TheJIT->getPointerToFunction(F); | 
|  | 702 | } | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 703 |  | 
|  | 704 | // Reacquire the lock to update the GOT map. | 
| Nicolas Geoffray | dcb31e1 | 2008-10-03 07:27:08 +0000 | [diff] [blame] | 705 | MutexGuard locked(TheJIT->lock); | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 706 |  | 
| Jeffrey Yasskin | ebbcef9 | 2009-10-19 18:49:59 +0000 | [diff] [blame] | 707 | // We might like to remove the call site from the CallSiteToFunction map, but | 
|  | 708 | // we can't do that! Multiple threads could be stuck, waiting to acquire the | 
|  | 709 | // lock above. As soon as the 1st function finishes compiling the function, | 
|  | 710 | // the next one will be released, and needs to be able to find the function it | 
|  | 711 | // needs to call. | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 712 |  | 
|  | 713 | // FIXME: We could rewrite all references to this stub if we knew them. | 
| Andrew Lenharth | 6a97461 | 2005-07-28 12:44:13 +0000 | [diff] [blame] | 714 |  | 
| Jeff Cohen | d29b6aa | 2005-07-30 18:33:25 +0000 | [diff] [blame] | 715 | // What we will do is set the compiled function address to map to the | 
|  | 716 | // same GOT entry as the stub so that later clients may update the GOT | 
| Andrew Lenharth | 6a97461 | 2005-07-28 12:44:13 +0000 | [diff] [blame] | 717 | // if they see it still using the stub address. | 
|  | 718 | // Note: this is done so the Resolver doesn't have to manage GOT memory | 
|  | 719 | // Do this without allocating map space if the target isn't using a GOT | 
|  | 720 | if(JR.revGOTMap.find(Stub) != JR.revGOTMap.end()) | 
|  | 721 | JR.revGOTMap[Result] = JR.revGOTMap[Stub]; | 
|  | 722 |  | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 723 | return Result; | 
|  | 724 | } | 
| Chris Lattner | 688506d | 2003-08-14 18:35:27 +0000 | [diff] [blame] | 725 |  | 
| Chris Lattner | 8ac66c1 | 2008-04-04 05:51:42 +0000 | [diff] [blame] | 726 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 166f226 | 2004-11-22 22:00:25 +0000 | [diff] [blame] | 727 | // JITEmitter code. | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 728 | // | 
| Chris Lattner | 166f226 | 2004-11-22 22:00:25 +0000 | [diff] [blame] | 729 | void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference, | 
| Jeffrey Yasskin | 2d27441 | 2009-11-07 08:51:52 +0000 | [diff] [blame] | 730 | bool MayNeedFarStub) { | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 731 | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 732 | return TheJIT->getOrEmitGlobalVariable(GV); | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 733 |  | 
| Chris Lattner | 18e0459 | 2008-06-25 20:21:35 +0000 | [diff] [blame] | 734 | if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) | 
| Anton Korobeynikov | 19e861a | 2008-09-09 20:05:04 +0000 | [diff] [blame] | 735 | return TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false)); | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 736 |  | 
|  | 737 | // If we have already compiled the function, return a pointer to its body. | 
|  | 738 | Function *F = cast<Function>(V); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 739 |  | 
|  | 740 | void *FnStub = Resolver.getFunctionStubIfAvailable(F); | 
|  | 741 | if (FnStub) { | 
|  | 742 | // Return the function stub if it's already created.  We do this first | 
|  | 743 | // so that we're returning the same address for the function as any | 
|  | 744 | // previous call. | 
|  | 745 | AddStubToCurrentFunction(FnStub); | 
|  | 746 | return FnStub; | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 747 | } | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 748 |  | 
|  | 749 | // Otherwise if we have code, go ahead and return that. | 
|  | 750 | void *ResultPtr = TheJIT->getPointerToGlobalIfAvailable(F); | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 751 | if (ResultPtr) return ResultPtr; | 
|  | 752 |  | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 753 | // If this is an external function pointer, we can force the JIT to | 
| Jeffrey Yasskin | 6f348e4 | 2009-11-09 22:34:19 +0000 | [diff] [blame] | 754 | // 'compile' it, which really just adds it to the map. | 
| Nate Begeman | b9c6c9b | 2009-03-07 06:41:19 +0000 | [diff] [blame] | 755 | if (F->isDeclaration() && !F->hasNotBeenReadFromBitcode() && | 
| Jeffrey Yasskin | 6f348e4 | 2009-11-09 22:34:19 +0000 | [diff] [blame] | 756 | !MayNeedFarStub) | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 757 | return TheJIT->getPointerToFunction(F); | 
| Chris Lattner | b43dbdc | 2004-11-22 07:24:43 +0000 | [diff] [blame] | 758 |  | 
| Chris Lattner | 5e22558 | 2004-11-21 03:37:42 +0000 | [diff] [blame] | 759 | // Okay, the function has not been compiled yet, if the target callback | 
|  | 760 | // mechanism is capable of rewriting the instruction directly, prefer to do | 
| Nate Begeman | b9c6c9b | 2009-03-07 06:41:19 +0000 | [diff] [blame] | 761 | // that instead of emitting a stub.  This uses the lazy resolver, so is not | 
|  | 762 | // legal if lazy compilation is disabled. | 
| Jeffrey Yasskin | 2d27441 | 2009-11-07 08:51:52 +0000 | [diff] [blame] | 763 | if (!MayNeedFarStub && TheJIT->isCompilingLazily()) | 
| Chris Lattner | e748401 | 2007-02-24 02:57:03 +0000 | [diff] [blame] | 764 | return Resolver.AddCallbackAtLocation(F, Reference); | 
| Chris Lattner | 5e22558 | 2004-11-21 03:37:42 +0000 | [diff] [blame] | 765 |  | 
| Nate Begeman | b9c6c9b | 2009-03-07 06:41:19 +0000 | [diff] [blame] | 766 | // Otherwise, we have to emit a stub. | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 767 | void *StubAddr = Resolver.getFunctionStub(F); | 
|  | 768 |  | 
|  | 769 | // Add the stub to the current function's list of referenced stubs, so we can | 
| Nate Begeman | b9c6c9b | 2009-03-07 06:41:19 +0000 | [diff] [blame] | 770 | // deallocate them if the current function is ever freed.  It's possible to | 
|  | 771 | // return null from getFunctionStub in the case of a weak extern that fails | 
|  | 772 | // to resolve. | 
|  | 773 | if (StubAddr) | 
|  | 774 | AddStubToCurrentFunction(StubAddr); | 
|  | 775 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 776 | return StubAddr; | 
| Chris Lattner | 5426652 | 2004-11-20 23:57:07 +0000 | [diff] [blame] | 777 | } | 
|  | 778 |  | 
| Jeffrey Yasskin | 2d27441 | 2009-11-07 08:51:52 +0000 | [diff] [blame] | 779 | void *JITEmitter::getPointerToGVIndirectSym(GlobalValue *V, void *Reference) { | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 780 | // Make sure GV is emitted first, and create a stub containing the fully | 
|  | 781 | // resolved address. | 
| Jeffrey Yasskin | 2d27441 | 2009-11-07 08:51:52 +0000 | [diff] [blame] | 782 | void *GVAddress = getPointerToGlobal(V, Reference, false); | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 783 | void *StubAddr = Resolver.getGlobalValueIndirectSym(V, GVAddress); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 784 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 785 | // Add the stub to the current function's list of referenced stubs, so we can | 
|  | 786 | // deallocate them if the current function is ever freed. | 
|  | 787 | AddStubToCurrentFunction(StubAddr); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 788 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 789 | return StubAddr; | 
|  | 790 | } | 
|  | 791 |  | 
|  | 792 | void JITEmitter::AddStubToCurrentFunction(void *StubAddr) { | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 793 | assert(CurFn && "Stub added to current function, but current function is 0!"); | 
| Jeffrey Yasskin | e5f8798 | 2009-10-13 21:32:57 +0000 | [diff] [blame] | 794 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 795 | SmallVectorImpl<void*> &StubsUsed = CurFnStubUses[CurFn]; | 
|  | 796 | StubsUsed.push_back(StubAddr); | 
|  | 797 |  | 
|  | 798 | SmallPtrSet<const Function *, 1> &FnRefs = StubFnRefs[StubAddr]; | 
|  | 799 | FnRefs.insert(CurFn); | 
| Evan Cheng | be8c03f | 2008-01-04 10:46:51 +0000 | [diff] [blame] | 800 | } | 
|  | 801 |  | 
| Devang Patel | 02c0423 | 2009-10-06 03:04:58 +0000 | [diff] [blame] | 802 | void JITEmitter::processDebugLoc(DebugLoc DL, bool BeforePrintingInsn) { | 
| Jeffrey Yasskin | 32360a7 | 2009-07-16 21:07:26 +0000 | [diff] [blame] | 803 | if (!DL.isUnknown()) { | 
|  | 804 | DebugLocTuple CurDLT = EmissionDetails.MF->getDebugLocTuple(DL); | 
|  | 805 |  | 
| Devang Patel | 02c0423 | 2009-10-06 03:04:58 +0000 | [diff] [blame] | 806 | if (BeforePrintingInsn) { | 
| Devang Patel | 1619dc3 | 2009-10-13 23:28:53 +0000 | [diff] [blame] | 807 | if (CurDLT.Scope != 0 && PrevDLT != CurDLT) { | 
| Devang Patel | 02c0423 | 2009-10-06 03:04:58 +0000 | [diff] [blame] | 808 | JITEvent_EmittedFunctionDetails::LineStart NextLine; | 
|  | 809 | NextLine.Address = getCurrentPCValue(); | 
|  | 810 | NextLine.Loc = DL; | 
|  | 811 | EmissionDetails.LineStarts.push_back(NextLine); | 
|  | 812 | } | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 813 |  | 
| Devang Patel | 02c0423 | 2009-10-06 03:04:58 +0000 | [diff] [blame] | 814 | PrevDLT = CurDLT; | 
| Jeffrey Yasskin | 32360a7 | 2009-07-16 21:07:26 +0000 | [diff] [blame] | 815 | } | 
| Jeffrey Yasskin | 32360a7 | 2009-07-16 21:07:26 +0000 | [diff] [blame] | 816 | } | 
|  | 817 | } | 
|  | 818 |  | 
| Evan Cheng | 1606e8e | 2009-03-13 07:51:59 +0000 | [diff] [blame] | 819 | static unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP, | 
|  | 820 | const TargetData *TD) { | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 821 | const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants(); | 
|  | 822 | if (Constants.empty()) return 0; | 
|  | 823 |  | 
| Evan Cheng | 1606e8e | 2009-03-13 07:51:59 +0000 | [diff] [blame] | 824 | unsigned Size = 0; | 
|  | 825 | for (unsigned i = 0, e = Constants.size(); i != e; ++i) { | 
|  | 826 | MachineConstantPoolEntry CPE = Constants[i]; | 
|  | 827 | unsigned AlignMask = CPE.getAlignment() - 1; | 
|  | 828 | Size = (Size + AlignMask) & ~AlignMask; | 
|  | 829 | const Type *Ty = CPE.getType(); | 
| Duncan Sands | 777d230 | 2009-05-09 07:06:46 +0000 | [diff] [blame] | 830 | Size += TD->getTypeAllocSize(Ty); | 
| Evan Cheng | 1606e8e | 2009-03-13 07:51:59 +0000 | [diff] [blame] | 831 | } | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 832 | return Size; | 
|  | 833 | } | 
|  | 834 |  | 
|  | 835 | static unsigned GetJumpTableSizeInBytes(MachineJumpTableInfo *MJTI) { | 
|  | 836 | const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); | 
|  | 837 | if (JT.empty()) return 0; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 838 |  | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 839 | unsigned NumEntries = 0; | 
|  | 840 | for (unsigned i = 0, e = JT.size(); i != e; ++i) | 
|  | 841 | NumEntries += JT[i].MBBs.size(); | 
|  | 842 |  | 
|  | 843 | unsigned EntrySize = MJTI->getEntrySize(); | 
|  | 844 |  | 
|  | 845 | return NumEntries * EntrySize; | 
|  | 846 | } | 
|  | 847 |  | 
| Nicolas Geoffray | 580631a | 2008-04-20 23:39:44 +0000 | [diff] [blame] | 848 | static uintptr_t RoundUpToAlign(uintptr_t Size, unsigned Alignment) { | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 849 | if (Alignment == 0) Alignment = 1; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 850 | // Since we do not know where the buffer will be allocated, be pessimistic. | 
| Nicolas Geoffray | 580631a | 2008-04-20 23:39:44 +0000 | [diff] [blame] | 851 | return Size + Alignment; | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 852 | } | 
| Evan Cheng | be8c03f | 2008-01-04 10:46:51 +0000 | [diff] [blame] | 853 |  | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 854 | /// addSizeOfGlobal - add the size of the global (plus any alignment padding) | 
|  | 855 | /// into the running total Size. | 
|  | 856 |  | 
|  | 857 | unsigned JITEmitter::addSizeOfGlobal(const GlobalVariable *GV, unsigned Size) { | 
|  | 858 | const Type *ElTy = GV->getType()->getElementType(); | 
| Duncan Sands | 777d230 | 2009-05-09 07:06:46 +0000 | [diff] [blame] | 859 | size_t GVSize = (size_t)TheJIT->getTargetData()->getTypeAllocSize(ElTy); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 860 | size_t GVAlign = | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 861 | (size_t)TheJIT->getTargetData()->getPreferredAlignment(GV); | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 862 | DEBUG(errs() << "JIT: Adding in size " << GVSize << " alignment " << GVAlign); | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 863 | DEBUG(GV->dump()); | 
|  | 864 | // Assume code section ends with worst possible alignment, so first | 
|  | 865 | // variable needs maximal padding. | 
|  | 866 | if (Size==0) | 
|  | 867 | Size = 1; | 
|  | 868 | Size = ((Size+GVAlign-1)/GVAlign)*GVAlign; | 
|  | 869 | Size += GVSize; | 
|  | 870 | return Size; | 
|  | 871 | } | 
|  | 872 |  | 
|  | 873 | /// addSizeOfGlobalsInConstantVal - find any globals that we haven't seen yet | 
|  | 874 | /// but are referenced from the constant; put them in GVSet and add their | 
|  | 875 | /// size into the running total Size. | 
|  | 876 |  | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 877 | unsigned JITEmitter::addSizeOfGlobalsInConstantVal(const Constant *C, | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 878 | unsigned Size) { | 
|  | 879 | // If its undefined, return the garbage. | 
|  | 880 | if (isa<UndefValue>(C)) | 
|  | 881 | return Size; | 
|  | 882 |  | 
|  | 883 | // If the value is a ConstantExpr | 
|  | 884 | if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { | 
|  | 885 | Constant *Op0 = CE->getOperand(0); | 
|  | 886 | switch (CE->getOpcode()) { | 
|  | 887 | case Instruction::GetElementPtr: | 
|  | 888 | case Instruction::Trunc: | 
|  | 889 | case Instruction::ZExt: | 
|  | 890 | case Instruction::SExt: | 
|  | 891 | case Instruction::FPTrunc: | 
|  | 892 | case Instruction::FPExt: | 
|  | 893 | case Instruction::UIToFP: | 
|  | 894 | case Instruction::SIToFP: | 
|  | 895 | case Instruction::FPToUI: | 
|  | 896 | case Instruction::FPToSI: | 
|  | 897 | case Instruction::PtrToInt: | 
|  | 898 | case Instruction::IntToPtr: | 
|  | 899 | case Instruction::BitCast: { | 
|  | 900 | Size = addSizeOfGlobalsInConstantVal(Op0, Size); | 
|  | 901 | break; | 
|  | 902 | } | 
|  | 903 | case Instruction::Add: | 
| Dan Gohman | ae3a0be | 2009-06-04 22:49:04 +0000 | [diff] [blame] | 904 | case Instruction::FAdd: | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 905 | case Instruction::Sub: | 
| Dan Gohman | ae3a0be | 2009-06-04 22:49:04 +0000 | [diff] [blame] | 906 | case Instruction::FSub: | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 907 | case Instruction::Mul: | 
| Dan Gohman | ae3a0be | 2009-06-04 22:49:04 +0000 | [diff] [blame] | 908 | case Instruction::FMul: | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 909 | case Instruction::UDiv: | 
|  | 910 | case Instruction::SDiv: | 
|  | 911 | case Instruction::URem: | 
|  | 912 | case Instruction::SRem: | 
|  | 913 | case Instruction::And: | 
|  | 914 | case Instruction::Or: | 
|  | 915 | case Instruction::Xor: { | 
|  | 916 | Size = addSizeOfGlobalsInConstantVal(Op0, Size); | 
|  | 917 | Size = addSizeOfGlobalsInConstantVal(CE->getOperand(1), Size); | 
|  | 918 | break; | 
|  | 919 | } | 
|  | 920 | default: { | 
| Torok Edwin | 7d696d8 | 2009-07-11 13:10:19 +0000 | [diff] [blame] | 921 | std::string msg; | 
|  | 922 | raw_string_ostream Msg(msg); | 
|  | 923 | Msg << "ConstantExpr not handled: " << *CE; | 
|  | 924 | llvm_report_error(Msg.str()); | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 925 | } | 
|  | 926 | } | 
|  | 927 | } | 
|  | 928 |  | 
|  | 929 | if (C->getType()->getTypeID() == Type::PointerTyID) | 
|  | 930 | if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(C)) | 
| Evan Cheng | 47c01a0 | 2008-11-07 09:02:17 +0000 | [diff] [blame] | 931 | if (GVSet.insert(GV)) | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 932 | Size = addSizeOfGlobal(GV, Size); | 
|  | 933 |  | 
|  | 934 | return Size; | 
|  | 935 | } | 
|  | 936 |  | 
|  | 937 | /// addSizeOfGLobalsInInitializer - handle any globals that we haven't seen yet | 
|  | 938 | /// but are referenced from the given initializer. | 
|  | 939 |  | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 940 | unsigned JITEmitter::addSizeOfGlobalsInInitializer(const Constant *Init, | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 941 | unsigned Size) { | 
|  | 942 | if (!isa<UndefValue>(Init) && | 
|  | 943 | !isa<ConstantVector>(Init) && | 
|  | 944 | !isa<ConstantAggregateZero>(Init) && | 
|  | 945 | !isa<ConstantArray>(Init) && | 
|  | 946 | !isa<ConstantStruct>(Init) && | 
|  | 947 | Init->getType()->isFirstClassType()) | 
|  | 948 | Size = addSizeOfGlobalsInConstantVal(Init, Size); | 
|  | 949 | return Size; | 
|  | 950 | } | 
|  | 951 |  | 
|  | 952 | /// GetSizeOfGlobalsInBytes - walk the code for the function, looking for | 
|  | 953 | /// globals; then walk the initializers of those globals looking for more. | 
|  | 954 | /// If their size has not been considered yet, add it into the running total | 
|  | 955 | /// Size. | 
|  | 956 |  | 
|  | 957 | unsigned JITEmitter::GetSizeOfGlobalsInBytes(MachineFunction &MF) { | 
|  | 958 | unsigned Size = 0; | 
|  | 959 | GVSet.clear(); | 
|  | 960 |  | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 961 | for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 962 | MBB != E; ++MBB) { | 
|  | 963 | for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); | 
|  | 964 | I != E; ++I) { | 
|  | 965 | const TargetInstrDesc &Desc = I->getDesc(); | 
|  | 966 | const MachineInstr &MI = *I; | 
|  | 967 | unsigned NumOps = Desc.getNumOperands(); | 
|  | 968 | for (unsigned CurOp = 0; CurOp < NumOps; CurOp++) { | 
|  | 969 | const MachineOperand &MO = MI.getOperand(CurOp); | 
| Dan Gohman | d735b80 | 2008-10-03 15:45:36 +0000 | [diff] [blame] | 970 | if (MO.isGlobal()) { | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 971 | GlobalValue* V = MO.getGlobal(); | 
|  | 972 | const GlobalVariable *GV = dyn_cast<const GlobalVariable>(V); | 
|  | 973 | if (!GV) | 
|  | 974 | continue; | 
|  | 975 | // If seen in previous function, it will have an entry here. | 
|  | 976 | if (TheJIT->getPointerToGlobalIfAvailable(GV)) | 
|  | 977 | continue; | 
|  | 978 | // If seen earlier in this function, it will have an entry here. | 
|  | 979 | // FIXME: it should be possible to combine these tables, by | 
|  | 980 | // assuming the addresses of the new globals in this module | 
|  | 981 | // start at 0 (or something) and adjusting them after codegen | 
|  | 982 | // complete.  Another possibility is to grab a marker bit in GV. | 
| Evan Cheng | 47c01a0 | 2008-11-07 09:02:17 +0000 | [diff] [blame] | 983 | if (GVSet.insert(GV)) | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 984 | // A variable as yet unseen.  Add in its size. | 
|  | 985 | Size = addSizeOfGlobal(GV, Size); | 
|  | 986 | } | 
|  | 987 | } | 
|  | 988 | } | 
|  | 989 | } | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 990 | DEBUG(errs() << "JIT: About to look through initializers\n"); | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 991 | // Look for more globals that are referenced only from initializers. | 
|  | 992 | // GVSet.end is computed each time because the set can grow as we go. | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 993 | for (SmallPtrSet<const GlobalVariable *, 8>::iterator I = GVSet.begin(); | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 994 | I != GVSet.end(); I++) { | 
|  | 995 | const GlobalVariable* GV = *I; | 
|  | 996 | if (GV->hasInitializer()) | 
|  | 997 | Size = addSizeOfGlobalsInInitializer(GV->getInitializer(), Size); | 
|  | 998 | } | 
|  | 999 |  | 
|  | 1000 | return Size; | 
|  | 1001 | } | 
|  | 1002 |  | 
| Chris Lattner | 166f226 | 2004-11-22 22:00:25 +0000 | [diff] [blame] | 1003 | void JITEmitter::startFunction(MachineFunction &F) { | 
| Daniel Dunbar | ce63ffb | 2009-07-25 00:23:56 +0000 | [diff] [blame] | 1004 | DEBUG(errs() << "JIT: Starting CodeGen of Function " | 
|  | 1005 | << F.getFunction()->getName() << "\n"); | 
| Evan Cheng | eb5d95a | 2008-11-06 17:46:04 +0000 | [diff] [blame] | 1006 |  | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 1007 | uintptr_t ActualSize = 0; | 
| Jim Grosbach | cce6c29 | 2008-10-03 16:17:20 +0000 | [diff] [blame] | 1008 | // Set the memory writable, if it's not already | 
|  | 1009 | MemMgr->setMemoryWritable(); | 
| Nicolas Geoffray | 5913e6c | 2008-04-20 17:44:19 +0000 | [diff] [blame] | 1010 | if (MemMgr->NeedsExactSize()) { | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1011 | DEBUG(errs() << "JIT: ExactSize\n"); | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 1012 | const TargetInstrInfo* TII = F.getTarget().getInstrInfo(); | 
|  | 1013 | MachineJumpTableInfo *MJTI = F.getJumpTableInfo(); | 
|  | 1014 | MachineConstantPool *MCP = F.getConstantPool(); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1015 |  | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 1016 | // Ensure the constant pool/jump table info is at least 4-byte aligned. | 
| Nicolas Geoffray | 580631a | 2008-04-20 23:39:44 +0000 | [diff] [blame] | 1017 | ActualSize = RoundUpToAlign(ActualSize, 16); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1018 |  | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 1019 | // Add the alignment of the constant pool | 
| Evan Cheng | 1606e8e | 2009-03-13 07:51:59 +0000 | [diff] [blame] | 1020 | ActualSize = RoundUpToAlign(ActualSize, MCP->getConstantPoolAlignment()); | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 1021 |  | 
|  | 1022 | // Add the constant pool size | 
| Evan Cheng | 1606e8e | 2009-03-13 07:51:59 +0000 | [diff] [blame] | 1023 | ActualSize += GetConstantPoolSizeInBytes(MCP, TheJIT->getTargetData()); | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 1024 |  | 
|  | 1025 | // Add the aligment of the jump table info | 
| Nicolas Geoffray | 580631a | 2008-04-20 23:39:44 +0000 | [diff] [blame] | 1026 | ActualSize = RoundUpToAlign(ActualSize, MJTI->getAlignment()); | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 1027 |  | 
|  | 1028 | // Add the jump table size | 
|  | 1029 | ActualSize += GetJumpTableSizeInBytes(MJTI); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1030 |  | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 1031 | // Add the alignment for the function | 
| Nicolas Geoffray | 580631a | 2008-04-20 23:39:44 +0000 | [diff] [blame] | 1032 | ActualSize = RoundUpToAlign(ActualSize, | 
|  | 1033 | std::max(F.getFunction()->getAlignment(), 8U)); | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 1034 |  | 
|  | 1035 | // Add the function size | 
|  | 1036 | ActualSize += TII->GetFunctionSizeInBytes(F); | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 1037 |  | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1038 | DEBUG(errs() << "JIT: ActualSize before globals " << ActualSize << "\n"); | 
| Dale Johannesen | dd947ea | 2008-08-07 01:30:15 +0000 | [diff] [blame] | 1039 | // Add the size of the globals that will be allocated after this function. | 
|  | 1040 | // These are all the ones referenced from this function that were not | 
|  | 1041 | // previously allocated. | 
|  | 1042 | ActualSize += GetSizeOfGlobalsInBytes(F); | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1043 | DEBUG(errs() << "JIT: ActualSize after globals " << ActualSize << "\n"); | 
| Reid Kleckner | 10b4fc5 | 2009-07-23 21:46:56 +0000 | [diff] [blame] | 1044 | } else if (SizeEstimate > 0) { | 
|  | 1045 | // SizeEstimate will be non-zero on reallocation attempts. | 
|  | 1046 | ActualSize = SizeEstimate; | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 1047 | } | 
|  | 1048 |  | 
| Chris Lattner | 8907b4b | 2007-12-05 23:39:57 +0000 | [diff] [blame] | 1049 | BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(), | 
|  | 1050 | ActualSize); | 
| Chris Lattner | e993cc2 | 2006-05-11 23:08:08 +0000 | [diff] [blame] | 1051 | BufferEnd = BufferBegin+ActualSize; | 
| Jeffrey Yasskin | 1e86132 | 2009-10-20 18:13:21 +0000 | [diff] [blame] | 1052 | EmittedFunctions[F.getFunction()].FunctionBody = BufferBegin; | 
|  | 1053 |  | 
| Evan Cheng | 9a1e9b9 | 2006-11-16 20:04:54 +0000 | [diff] [blame] | 1054 | // Ensure the constant pool/jump table info is at least 4-byte aligned. | 
|  | 1055 | emitAlignment(16); | 
|  | 1056 |  | 
| Chris Lattner | f75f9be | 2006-05-02 23:22:24 +0000 | [diff] [blame] | 1057 | emitConstantPool(F.getConstantPool()); | 
|  | 1058 | initJumpTableInfo(F.getJumpTableInfo()); | 
|  | 1059 |  | 
|  | 1060 | // About to start emitting the machine code for the function. | 
| Chris Lattner | 0eb4d6b | 2006-05-03 01:03:20 +0000 | [diff] [blame] | 1061 | emitAlignment(std::max(F.getFunction()->getAlignment(), 8U)); | 
| Chris Lattner | f75f9be | 2006-05-02 23:22:24 +0000 | [diff] [blame] | 1062 | TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr); | 
| Jeffrey Yasskin | 7a9034c | 2009-10-27 00:03:05 +0000 | [diff] [blame] | 1063 | EmittedFunctions[F.getFunction()].Code = CurBufferPtr; | 
| Evan Cheng | 55fc280 | 2006-07-25 20:40:54 +0000 | [diff] [blame] | 1064 |  | 
| Chris Lattner | b4432f3 | 2006-05-03 17:10:41 +0000 | [diff] [blame] | 1065 | MBBLocations.clear(); | 
| Jeffrey Yasskin | 32360a7 | 2009-07-16 21:07:26 +0000 | [diff] [blame] | 1066 |  | 
|  | 1067 | EmissionDetails.MF = &F; | 
|  | 1068 | EmissionDetails.LineStarts.clear(); | 
| Chris Lattner | bd199fb | 2002-12-24 00:01:05 +0000 | [diff] [blame] | 1069 | } | 
|  | 1070 |  | 
| Chris Lattner | 43b429b | 2006-05-02 18:27:26 +0000 | [diff] [blame] | 1071 | bool JITEmitter::finishFunction(MachineFunction &F) { | 
| Chris Lattner | e993cc2 | 2006-05-11 23:08:08 +0000 | [diff] [blame] | 1072 | if (CurBufferPtr == BufferEnd) { | 
| Reid Kleckner | 10b4fc5 | 2009-07-23 21:46:56 +0000 | [diff] [blame] | 1073 | // We must call endFunctionBody before retrying, because | 
|  | 1074 | // deallocateMemForFunction requires it. | 
|  | 1075 | MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr); | 
|  | 1076 | retryWithMoreMemory(F); | 
|  | 1077 | return true; | 
| Chris Lattner | e993cc2 | 2006-05-11 23:08:08 +0000 | [diff] [blame] | 1078 | } | 
| Reid Kleckner | 10b4fc5 | 2009-07-23 21:46:56 +0000 | [diff] [blame] | 1079 |  | 
| Jim Laskey | b92767a | 2006-12-14 22:53:42 +0000 | [diff] [blame] | 1080 | emitJumpTableInfo(F.getJumpTableInfo()); | 
| Reid Kleckner | 10b4fc5 | 2009-07-23 21:46:56 +0000 | [diff] [blame] | 1081 |  | 
| Chris Lattner | a827953 | 2006-06-16 18:09:26 +0000 | [diff] [blame] | 1082 | // FnStart is the start of the text, not the start of the constant pool and | 
|  | 1083 | // other per-function data. | 
| Bruno Cardoso Lopes | 186c670 | 2009-06-04 00:15:51 +0000 | [diff] [blame] | 1084 | uint8_t *FnStart = | 
|  | 1085 | (uint8_t *)TheJIT->getPointerToGlobalIfAvailable(F.getFunction()); | 
| Chris Lattner | bd199fb | 2002-12-24 00:01:05 +0000 | [diff] [blame] | 1086 |  | 
| Argyrios Kyrtzidis | 19fee41 | 2009-04-30 23:01:58 +0000 | [diff] [blame] | 1087 | // FnEnd is the end of the function's machine code. | 
| Bruno Cardoso Lopes | 186c670 | 2009-06-04 00:15:51 +0000 | [diff] [blame] | 1088 | uint8_t *FnEnd = CurBufferPtr; | 
| Argyrios Kyrtzidis | 19fee41 | 2009-04-30 23:01:58 +0000 | [diff] [blame] | 1089 |  | 
| Chris Lattner | 5be478f | 2004-11-20 03:46:14 +0000 | [diff] [blame] | 1090 | if (!Relocations.empty()) { | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 1091 | CurFn = F.getFunction(); | 
| Chris Lattner | e884dc2 | 2005-07-20 16:29:20 +0000 | [diff] [blame] | 1092 | NumRelos += Relocations.size(); | 
|  | 1093 |  | 
| Chris Lattner | 5be478f | 2004-11-20 03:46:14 +0000 | [diff] [blame] | 1094 | // Resolve the relocations to concrete pointers. | 
|  | 1095 | for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { | 
|  | 1096 | MachineRelocation &MR = Relocations[i]; | 
| Evan Cheng | 9200605 | 2008-11-03 07:14:02 +0000 | [diff] [blame] | 1097 | void *ResultPtr = 0; | 
| Evan Cheng | ef5784e | 2008-10-29 23:54:46 +0000 | [diff] [blame] | 1098 | if (!MR.letTargetResolve()) { | 
| Evan Cheng | d7398c9 | 2008-11-08 07:37:34 +0000 | [diff] [blame] | 1099 | if (MR.isExternalSymbol()) { | 
| Dan Gohman | 69f9378 | 2009-01-05 05:32:42 +0000 | [diff] [blame] | 1100 | ResultPtr = TheJIT->getPointerToNamedFunction(MR.getExternalSymbol(), | 
|  | 1101 | false); | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1102 | DEBUG(errs() << "JIT: Map \'" << MR.getExternalSymbol() << "\' to [" | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1103 | << ResultPtr << "]\n"); | 
| Misha Brukman | f976c85 | 2005-04-21 22:55:34 +0000 | [diff] [blame] | 1104 |  | 
| Evan Cheng | ef5784e | 2008-10-29 23:54:46 +0000 | [diff] [blame] | 1105 | // If the target REALLY wants a stub for this function, emit it now. | 
| Jeffrey Yasskin | 2d27441 | 2009-11-07 08:51:52 +0000 | [diff] [blame] | 1106 | if (MR.mayNeedFarStub()) { | 
| Jeffrey Yasskin | 6f348e4 | 2009-11-09 22:34:19 +0000 | [diff] [blame] | 1107 | ResultPtr = Resolver.getExternalFunctionStub(ResultPtr); | 
| Nate Begeman | 841c6a4 | 2009-03-11 07:03:43 +0000 | [diff] [blame] | 1108 | } | 
| Evan Cheng | ef5784e | 2008-10-29 23:54:46 +0000 | [diff] [blame] | 1109 | } else if (MR.isGlobalValue()) { | 
|  | 1110 | ResultPtr = getPointerToGlobal(MR.getGlobalValue(), | 
|  | 1111 | BufferBegin+MR.getMachineCodeOffset(), | 
| Jeffrey Yasskin | 2d27441 | 2009-11-07 08:51:52 +0000 | [diff] [blame] | 1112 | MR.mayNeedFarStub()); | 
| Evan Cheng | 5594f12 | 2008-11-10 01:52:24 +0000 | [diff] [blame] | 1113 | } else if (MR.isIndirectSymbol()) { | 
| Jeffrey Yasskin | 2d27441 | 2009-11-07 08:51:52 +0000 | [diff] [blame] | 1114 | ResultPtr = getPointerToGVIndirectSym( | 
|  | 1115 | MR.getGlobalValue(), BufferBegin+MR.getMachineCodeOffset()); | 
| Evan Cheng | ef5784e | 2008-10-29 23:54:46 +0000 | [diff] [blame] | 1116 | } else if (MR.isBasicBlock()) { | 
|  | 1117 | ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock()); | 
|  | 1118 | } else if (MR.isConstantPoolIndex()) { | 
|  | 1119 | ResultPtr = (void*)getConstantPoolEntryAddress(MR.getConstantPoolIndex()); | 
|  | 1120 | } else { | 
|  | 1121 | assert(MR.isJumpTableIndex()); | 
|  | 1122 | ResultPtr=(void*)getJumpTableEntryAddress(MR.getJumpTableIndex()); | 
|  | 1123 | } | 
| Jeff Cohen | 00b16889 | 2005-07-27 06:12:32 +0000 | [diff] [blame] | 1124 |  | 
| Evan Cheng | ef5784e | 2008-10-29 23:54:46 +0000 | [diff] [blame] | 1125 | MR.setResultPointer(ResultPtr); | 
|  | 1126 | } | 
| Andrew Lenharth | 16ec33c | 2005-07-22 20:48:12 +0000 | [diff] [blame] | 1127 |  | 
| Andrew Lenharth | 6a97461 | 2005-07-28 12:44:13 +0000 | [diff] [blame] | 1128 | // if we are managing the GOT and the relocation wants an index, | 
|  | 1129 | // give it one | 
| Chris Lattner | 8907b4b | 2007-12-05 23:39:57 +0000 | [diff] [blame] | 1130 | if (MR.isGOTRelative() && MemMgr->isManagingGOT()) { | 
| Chris Lattner | e748401 | 2007-02-24 02:57:03 +0000 | [diff] [blame] | 1131 | unsigned idx = Resolver.getGOTIndexForAddr(ResultPtr); | 
| Andrew Lenharth | 6a97461 | 2005-07-28 12:44:13 +0000 | [diff] [blame] | 1132 | MR.setGOTIndex(idx); | 
| Chris Lattner | 8907b4b | 2007-12-05 23:39:57 +0000 | [diff] [blame] | 1133 | if (((void**)MemMgr->getGOTBase())[idx] != ResultPtr) { | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1134 | DEBUG(errs() << "JIT: GOT was out of date for " << ResultPtr | 
|  | 1135 | << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] | 
|  | 1136 | << "\n"); | 
| Chris Lattner | 8907b4b | 2007-12-05 23:39:57 +0000 | [diff] [blame] | 1137 | ((void**)MemMgr->getGOTBase())[idx] = ResultPtr; | 
| Andrew Lenharth | 6a97461 | 2005-07-28 12:44:13 +0000 | [diff] [blame] | 1138 | } | 
| Andrew Lenharth | 16ec33c | 2005-07-22 20:48:12 +0000 | [diff] [blame] | 1139 | } | 
| Chris Lattner | 5be478f | 2004-11-20 03:46:14 +0000 | [diff] [blame] | 1140 | } | 
|  | 1141 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 1142 | CurFn = 0; | 
| Chris Lattner | 43b429b | 2006-05-02 18:27:26 +0000 | [diff] [blame] | 1143 | TheJIT->getJITInfo().relocate(BufferBegin, &Relocations[0], | 
| Chris Lattner | 8907b4b | 2007-12-05 23:39:57 +0000 | [diff] [blame] | 1144 | Relocations.size(), MemMgr->getGOTBase()); | 
| Chris Lattner | 5be478f | 2004-11-20 03:46:14 +0000 | [diff] [blame] | 1145 | } | 
|  | 1146 |  | 
| Chris Lattner | d2d5c76 | 2006-05-03 18:55:56 +0000 | [diff] [blame] | 1147 | // Update the GOT entry for F to point to the new code. | 
| Chris Lattner | 8907b4b | 2007-12-05 23:39:57 +0000 | [diff] [blame] | 1148 | if (MemMgr->isManagingGOT()) { | 
| Chris Lattner | e748401 | 2007-02-24 02:57:03 +0000 | [diff] [blame] | 1149 | unsigned idx = Resolver.getGOTIndexForAddr((void*)BufferBegin); | 
| Chris Lattner | 8907b4b | 2007-12-05 23:39:57 +0000 | [diff] [blame] | 1150 | if (((void**)MemMgr->getGOTBase())[idx] != (void*)BufferBegin) { | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1151 | DEBUG(errs() << "JIT: GOT was out of date for " << (void*)BufferBegin | 
|  | 1152 | << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] | 
|  | 1153 | << "\n"); | 
| Chris Lattner | 8907b4b | 2007-12-05 23:39:57 +0000 | [diff] [blame] | 1154 | ((void**)MemMgr->getGOTBase())[idx] = (void*)BufferBegin; | 
| Andrew Lenharth | 6a97461 | 2005-07-28 12:44:13 +0000 | [diff] [blame] | 1155 | } | 
|  | 1156 | } | 
|  | 1157 |  | 
| Argyrios Kyrtzidis | 19fee41 | 2009-04-30 23:01:58 +0000 | [diff] [blame] | 1158 | // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for | 
|  | 1159 | // global variables that were referenced in the relocations. | 
|  | 1160 | MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr); | 
| Evan Cheng | 5788d1a | 2008-12-10 02:32:19 +0000 | [diff] [blame] | 1161 |  | 
|  | 1162 | if (CurBufferPtr == BufferEnd) { | 
| Reid Kleckner | 10b4fc5 | 2009-07-23 21:46:56 +0000 | [diff] [blame] | 1163 | retryWithMoreMemory(F); | 
|  | 1164 | return true; | 
|  | 1165 | } else { | 
|  | 1166 | // Now that we've succeeded in emitting the function, reset the | 
|  | 1167 | // SizeEstimate back down to zero. | 
|  | 1168 | SizeEstimate = 0; | 
| Evan Cheng | 5788d1a | 2008-12-10 02:32:19 +0000 | [diff] [blame] | 1169 | } | 
|  | 1170 |  | 
| Nuno Lopes | cef7527 | 2008-10-21 11:42:16 +0000 | [diff] [blame] | 1171 | BufferBegin = CurBufferPtr = 0; | 
|  | 1172 | NumBytes += FnEnd-FnStart; | 
|  | 1173 |  | 
| Evan Cheng | 55fc280 | 2006-07-25 20:40:54 +0000 | [diff] [blame] | 1174 | // Invalidate the icache if necessary. | 
| Chris Lattner | bc52cad | 2008-06-25 17:18:44 +0000 | [diff] [blame] | 1175 | sys::Memory::InvalidateInstructionCache(FnStart, FnEnd-FnStart); | 
| Jeffrey Yasskin | df5a7da | 2009-06-25 02:04:04 +0000 | [diff] [blame] | 1176 |  | 
| Jeffrey Yasskin | df5a7da | 2009-06-25 02:04:04 +0000 | [diff] [blame] | 1177 | TheJIT->NotifyFunctionEmitted(*F.getFunction(), FnStart, FnEnd-FnStart, | 
| Jeffrey Yasskin | 32360a7 | 2009-07-16 21:07:26 +0000 | [diff] [blame] | 1178 | EmissionDetails); | 
| Evan Cheng | 55fc280 | 2006-07-25 20:40:54 +0000 | [diff] [blame] | 1179 |  | 
| Daniel Dunbar | ce63ffb | 2009-07-25 00:23:56 +0000 | [diff] [blame] | 1180 | DEBUG(errs() << "JIT: Finished CodeGen of [" << (void*)FnStart | 
|  | 1181 | << "] Function: " << F.getFunction()->getName() | 
|  | 1182 | << ": " << (FnEnd-FnStart) << " bytes of text, " | 
|  | 1183 | << Relocations.size() << " relocations\n"); | 
| Argyrios Kyrtzidis | b3a847d | 2009-05-18 21:06:40 +0000 | [diff] [blame] | 1184 |  | 
| Chris Lattner | 5be478f | 2004-11-20 03:46:14 +0000 | [diff] [blame] | 1185 | Relocations.clear(); | 
| Evan Cheng | 1606e8e | 2009-03-13 07:51:59 +0000 | [diff] [blame] | 1186 | ConstPoolAddresses.clear(); | 
| Anton Korobeynikov | 8cd4c3e | 2007-01-19 17:25:17 +0000 | [diff] [blame] | 1187 |  | 
| Evan Cheng | bc4707a | 2008-09-18 07:54:21 +0000 | [diff] [blame] | 1188 | // Mark code region readable and executable if it's not so already. | 
| Jim Grosbach | cce6c29 | 2008-10-03 16:17:20 +0000 | [diff] [blame] | 1189 | MemMgr->setMemoryExecutable(); | 
| Evan Cheng | bc4707a | 2008-09-18 07:54:21 +0000 | [diff] [blame] | 1190 |  | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1191 | DEBUG( | 
| Evan Cheng | e7c3551 | 2008-11-12 08:22:43 +0000 | [diff] [blame] | 1192 | if (sys::hasDisassembler()) { | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1193 | errs() << "JIT: Disassembled code:\n"; | 
|  | 1194 | errs() << sys::disassembleBuffer(FnStart, FnEnd-FnStart, | 
|  | 1195 | (uintptr_t)FnStart); | 
| Evan Cheng | e7c3551 | 2008-11-12 08:22:43 +0000 | [diff] [blame] | 1196 | } else { | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1197 | errs() << "JIT: Binary code:\n"; | 
| Bruno Cardoso Lopes | 186c670 | 2009-06-04 00:15:51 +0000 | [diff] [blame] | 1198 | uint8_t* q = FnStart; | 
| Evan Cheng | e7c3551 | 2008-11-12 08:22:43 +0000 | [diff] [blame] | 1199 | for (int i = 0; q < FnEnd; q += 4, ++i) { | 
|  | 1200 | if (i == 4) | 
|  | 1201 | i = 0; | 
|  | 1202 | if (i == 0) | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1203 | errs() << "JIT: " << (long)(q - FnStart) << ": "; | 
| Evan Cheng | e7c3551 | 2008-11-12 08:22:43 +0000 | [diff] [blame] | 1204 | bool Done = false; | 
|  | 1205 | for (int j = 3; j >= 0; --j) { | 
|  | 1206 | if (q + j >= FnEnd) | 
|  | 1207 | Done = true; | 
|  | 1208 | else | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1209 | errs() << (unsigned short)q[j]; | 
| Evan Cheng | e7c3551 | 2008-11-12 08:22:43 +0000 | [diff] [blame] | 1210 | } | 
|  | 1211 | if (Done) | 
|  | 1212 | break; | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1213 | errs() << ' '; | 
| Evan Cheng | e7c3551 | 2008-11-12 08:22:43 +0000 | [diff] [blame] | 1214 | if (i == 3) | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1215 | errs() << '\n'; | 
| Evan Cheng | a7916f5 | 2008-11-05 23:44:08 +0000 | [diff] [blame] | 1216 | } | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1217 | errs()<< '\n'; | 
| Evan Cheng | a7916f5 | 2008-11-05 23:44:08 +0000 | [diff] [blame] | 1218 | } | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1219 | ); | 
|  | 1220 |  | 
| Reid Kleckner | 2763217 | 2009-09-20 23:52:43 +0000 | [diff] [blame] | 1221 | if (DwarfExceptionHandling || JITEmitDebugInfo) { | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 1222 | uintptr_t ActualSize = 0; | 
| Nicolas Geoffray | afe6c2b | 2008-02-13 18:39:37 +0000 | [diff] [blame] | 1223 | SavedBufferBegin = BufferBegin; | 
|  | 1224 | SavedBufferEnd = BufferEnd; | 
|  | 1225 | SavedCurBufferPtr = CurBufferPtr; | 
| Reid Kleckner | 2763217 | 2009-09-20 23:52:43 +0000 | [diff] [blame] | 1226 |  | 
| Nicolas Geoffray | 5913e6c | 2008-04-20 17:44:19 +0000 | [diff] [blame] | 1227 | if (MemMgr->NeedsExactSize()) { | 
|  | 1228 | ActualSize = DE->GetDwarfTableSizeInBytes(F, *this, FnStart, FnEnd); | 
| Nicolas Geoffray | dc17ab2 | 2008-04-18 20:59:31 +0000 | [diff] [blame] | 1229 | } | 
| Nicolas Geoffray | afe6c2b | 2008-02-13 18:39:37 +0000 | [diff] [blame] | 1230 |  | 
|  | 1231 | BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(), | 
|  | 1232 | ActualSize); | 
|  | 1233 | BufferEnd = BufferBegin+ActualSize; | 
| Jeffrey Yasskin | 1e86132 | 2009-10-20 18:13:21 +0000 | [diff] [blame] | 1234 | EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin; | 
| Reid Kleckner | 2763217 | 2009-09-20 23:52:43 +0000 | [diff] [blame] | 1235 | uint8_t *EhStart; | 
|  | 1236 | uint8_t *FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd, | 
|  | 1237 | EhStart); | 
| Chris Lattner | 0fdaa0b | 2008-03-07 20:05:43 +0000 | [diff] [blame] | 1238 | MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr, | 
|  | 1239 | FrameRegister); | 
| Reid Kleckner | 2763217 | 2009-09-20 23:52:43 +0000 | [diff] [blame] | 1240 | uint8_t *EhEnd = CurBufferPtr; | 
| Nicolas Geoffray | afe6c2b | 2008-02-13 18:39:37 +0000 | [diff] [blame] | 1241 | BufferBegin = SavedBufferBegin; | 
|  | 1242 | BufferEnd = SavedBufferEnd; | 
|  | 1243 | CurBufferPtr = SavedCurBufferPtr; | 
|  | 1244 |  | 
| Reid Kleckner | 2763217 | 2009-09-20 23:52:43 +0000 | [diff] [blame] | 1245 | if (DwarfExceptionHandling) { | 
|  | 1246 | TheJIT->RegisterTable(FrameRegister); | 
|  | 1247 | } | 
|  | 1248 |  | 
|  | 1249 | if (JITEmitDebugInfo) { | 
|  | 1250 | DebugInfo I; | 
|  | 1251 | I.FnStart = FnStart; | 
|  | 1252 | I.FnEnd = FnEnd; | 
|  | 1253 | I.EhStart = EhStart; | 
|  | 1254 | I.EhEnd = EhEnd; | 
|  | 1255 | DR->RegisterFunction(F.getFunction(), I); | 
|  | 1256 | } | 
| Nicolas Geoffray | afe6c2b | 2008-02-13 18:39:37 +0000 | [diff] [blame] | 1257 | } | 
| Evan Cheng | 252ddfb | 2008-09-02 08:14:01 +0000 | [diff] [blame] | 1258 |  | 
|  | 1259 | if (MMI) | 
|  | 1260 | MMI->EndFunction(); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1261 |  | 
| Chris Lattner | 43b429b | 2006-05-02 18:27:26 +0000 | [diff] [blame] | 1262 | return false; | 
| Chris Lattner | bd199fb | 2002-12-24 00:01:05 +0000 | [diff] [blame] | 1263 | } | 
|  | 1264 |  | 
| Reid Kleckner | 10b4fc5 | 2009-07-23 21:46:56 +0000 | [diff] [blame] | 1265 | void JITEmitter::retryWithMoreMemory(MachineFunction &F) { | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1266 | DEBUG(errs() << "JIT: Ran out of space for native code.  Reattempting.\n"); | 
| Reid Kleckner | 10b4fc5 | 2009-07-23 21:46:56 +0000 | [diff] [blame] | 1267 | Relocations.clear();  // Clear the old relocations or we'll reapply them. | 
|  | 1268 | ConstPoolAddresses.clear(); | 
|  | 1269 | ++NumRetries; | 
|  | 1270 | deallocateMemForFunction(F.getFunction()); | 
|  | 1271 | // Try again with at least twice as much free space. | 
|  | 1272 | SizeEstimate = (uintptr_t)(2 * (BufferEnd - BufferBegin)); | 
|  | 1273 | } | 
|  | 1274 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 1275 | /// deallocateMemForFunction - Deallocate all memory for the specified | 
|  | 1276 | /// function body.  Also drop any references the function has to stubs. | 
| Jeffrey Yasskin | 7a9034c | 2009-10-27 00:03:05 +0000 | [diff] [blame] | 1277 | /// May be called while the Function is being destroyed inside ~Value(). | 
| Reid Kleckner | 10b4fc5 | 2009-07-23 21:46:56 +0000 | [diff] [blame] | 1278 | void JITEmitter::deallocateMemForFunction(const Function *F) { | 
| Jeffrey Yasskin | 7a9034c | 2009-10-27 00:03:05 +0000 | [diff] [blame] | 1279 | ValueMap<const Function *, EmittedCode, EmittedFunctionConfig>::iterator | 
|  | 1280 | Emitted = EmittedFunctions.find(F); | 
| Jeffrey Yasskin | 1e86132 | 2009-10-20 18:13:21 +0000 | [diff] [blame] | 1281 | if (Emitted != EmittedFunctions.end()) { | 
|  | 1282 | MemMgr->deallocateFunctionBody(Emitted->second.FunctionBody); | 
|  | 1283 | MemMgr->deallocateExceptionTable(Emitted->second.ExceptionTable); | 
| Jeffrey Yasskin | 7a9034c | 2009-10-27 00:03:05 +0000 | [diff] [blame] | 1284 | TheJIT->NotifyFreeingMachineCode(Emitted->second.Code); | 
|  | 1285 |  | 
| Jeffrey Yasskin | 1e86132 | 2009-10-20 18:13:21 +0000 | [diff] [blame] | 1286 | EmittedFunctions.erase(Emitted); | 
|  | 1287 | } | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 1288 |  | 
| Reid Kleckner | 2763217 | 2009-09-20 23:52:43 +0000 | [diff] [blame] | 1289 | // TODO: Do we need to unregister exception handling information from libgcc | 
|  | 1290 | // here? | 
|  | 1291 |  | 
|  | 1292 | if (JITEmitDebugInfo) { | 
|  | 1293 | DR->UnregisterFunction(F); | 
|  | 1294 | } | 
|  | 1295 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 1296 | // If the function did not reference any stubs, return. | 
|  | 1297 | if (CurFnStubUses.find(F) == CurFnStubUses.end()) | 
|  | 1298 | return; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1299 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 1300 | // For each referenced stub, erase the reference to this function, and then | 
|  | 1301 | // erase the list of referenced stubs. | 
|  | 1302 | SmallVectorImpl<void *> &StubList = CurFnStubUses[F]; | 
|  | 1303 | for (unsigned i = 0, e = StubList.size(); i != e; ++i) { | 
|  | 1304 | void *Stub = StubList[i]; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1305 |  | 
| Nate Begeman | 841c6a4 | 2009-03-11 07:03:43 +0000 | [diff] [blame] | 1306 | // If we already invalidated this stub for this function, continue. | 
|  | 1307 | if (StubFnRefs.count(Stub) == 0) | 
|  | 1308 | continue; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1309 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 1310 | SmallPtrSet<const Function *, 1> &FnRefs = StubFnRefs[Stub]; | 
|  | 1311 | FnRefs.erase(F); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1312 |  | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 1313 | // If this function was the last reference to the stub, invalidate the stub | 
|  | 1314 | // in the JITResolver.  Were there a memory manager deallocateStub routine, | 
|  | 1315 | // we could call that at this point too. | 
|  | 1316 | if (FnRefs.empty()) { | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1317 | DEBUG(errs() << "\nJIT: Invalidated Stub at [" << Stub << "]\n"); | 
| Nate Begeman | 841c6a4 | 2009-03-11 07:03:43 +0000 | [diff] [blame] | 1318 | StubFnRefs.erase(Stub); | 
|  | 1319 |  | 
|  | 1320 | // Invalidate the stub.  If it is a GV stub, update the JIT's global | 
| Jeffrey Yasskin | 6f348e4 | 2009-11-09 22:34:19 +0000 | [diff] [blame] | 1321 | // mapping for that GV to zero. | 
| Nate Begeman | b9c6c9b | 2009-03-07 06:41:19 +0000 | [diff] [blame] | 1322 | GlobalValue *GV = Resolver.invalidateStub(Stub); | 
| Nate Begeman | 841c6a4 | 2009-03-11 07:03:43 +0000 | [diff] [blame] | 1323 | if (GV) { | 
|  | 1324 | TheJIT->updateGlobalMapping(GV, 0); | 
| Nate Begeman | 841c6a4 | 2009-03-11 07:03:43 +0000 | [diff] [blame] | 1325 | } | 
| Nate Begeman | 50cd6fd | 2009-03-05 06:34:37 +0000 | [diff] [blame] | 1326 | } | 
|  | 1327 | } | 
|  | 1328 | CurFnStubUses.erase(F); | 
|  | 1329 | } | 
|  | 1330 |  | 
|  | 1331 |  | 
| Evan Cheng | 5788d1a | 2008-12-10 02:32:19 +0000 | [diff] [blame] | 1332 | void* JITEmitter::allocateSpace(uintptr_t Size, unsigned Alignment) { | 
| Nuno Lopes | cef7527 | 2008-10-21 11:42:16 +0000 | [diff] [blame] | 1333 | if (BufferBegin) | 
| Bruno Cardoso Lopes | a3f99f9 | 2009-05-30 20:51:52 +0000 | [diff] [blame] | 1334 | return JITCodeEmitter::allocateSpace(Size, Alignment); | 
| Nuno Lopes | cef7527 | 2008-10-21 11:42:16 +0000 | [diff] [blame] | 1335 |  | 
|  | 1336 | // create a new memory block if there is no active one. | 
|  | 1337 | // care must be taken so that BufferBegin is invalidated when a | 
|  | 1338 | // block is trimmed | 
|  | 1339 | BufferBegin = CurBufferPtr = MemMgr->allocateSpace(Size, Alignment); | 
|  | 1340 | BufferEnd = BufferBegin+Size; | 
|  | 1341 | return CurBufferPtr; | 
|  | 1342 | } | 
|  | 1343 |  | 
| Jeffrey Yasskin | 489393d | 2009-07-08 21:59:57 +0000 | [diff] [blame] | 1344 | void* JITEmitter::allocateGlobal(uintptr_t Size, unsigned Alignment) { | 
|  | 1345 | // Delegate this call through the memory manager. | 
|  | 1346 | return MemMgr->allocateGlobal(Size, Alignment); | 
|  | 1347 | } | 
|  | 1348 |  | 
| Chris Lattner | 166f226 | 2004-11-22 22:00:25 +0000 | [diff] [blame] | 1349 | void JITEmitter::emitConstantPool(MachineConstantPool *MCP) { | 
| Evan Cheng | 47c01a0 | 2008-11-07 09:02:17 +0000 | [diff] [blame] | 1350 | if (TheJIT->getJITInfo().hasCustomConstantPool()) | 
| Jim Grosbach | 8fe9535 | 2008-10-30 23:44:39 +0000 | [diff] [blame] | 1351 | return; | 
| Evan Cheng | 47c01a0 | 2008-11-07 09:02:17 +0000 | [diff] [blame] | 1352 |  | 
| Chris Lattner | fa77d43 | 2006-02-09 04:22:52 +0000 | [diff] [blame] | 1353 | const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants(); | 
| Chris Lattner | 2c0a6a1 | 2003-11-30 04:23:21 +0000 | [diff] [blame] | 1354 | if (Constants.empty()) return; | 
|  | 1355 |  | 
| Evan Cheng | 1606e8e | 2009-03-13 07:51:59 +0000 | [diff] [blame] | 1356 | unsigned Size = GetConstantPoolSizeInBytes(MCP, TheJIT->getTargetData()); | 
|  | 1357 | unsigned Align = MCP->getConstantPoolAlignment(); | 
| Evan Cheng | 97b8c40 | 2008-04-12 00:22:01 +0000 | [diff] [blame] | 1358 | ConstantPoolBase = allocateSpace(Size, Align); | 
| Chris Lattner | 239862c | 2006-02-09 04:49:59 +0000 | [diff] [blame] | 1359 | ConstantPool = MCP; | 
| Chris Lattner | f75f9be | 2006-05-02 23:22:24 +0000 | [diff] [blame] | 1360 |  | 
|  | 1361 | if (ConstantPoolBase == 0) return;  // Buffer overflow. | 
|  | 1362 |  | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1363 | DEBUG(errs() << "JIT: Emitted constant pool at [" << ConstantPoolBase | 
|  | 1364 | << "] (size: " << Size << ", alignment: " << Align << ")\n"); | 
| Evan Cheng | 97b8c40 | 2008-04-12 00:22:01 +0000 | [diff] [blame] | 1365 |  | 
| Chris Lattner | 239862c | 2006-02-09 04:49:59 +0000 | [diff] [blame] | 1366 | // Initialize the memory for all of the constant pool entries. | 
| Evan Cheng | 1606e8e | 2009-03-13 07:51:59 +0000 | [diff] [blame] | 1367 | unsigned Offset = 0; | 
| Chris Lattner | 3029f92 | 2006-02-09 04:46:04 +0000 | [diff] [blame] | 1368 | for (unsigned i = 0, e = Constants.size(); i != e; ++i) { | 
| Evan Cheng | 1606e8e | 2009-03-13 07:51:59 +0000 | [diff] [blame] | 1369 | MachineConstantPoolEntry CPE = Constants[i]; | 
|  | 1370 | unsigned AlignMask = CPE.getAlignment() - 1; | 
|  | 1371 | Offset = (Offset + AlignMask) & ~AlignMask; | 
|  | 1372 |  | 
|  | 1373 | uintptr_t CAddr = (uintptr_t)ConstantPoolBase + Offset; | 
|  | 1374 | ConstPoolAddresses.push_back(CAddr); | 
|  | 1375 | if (CPE.isMachineConstantPoolEntry()) { | 
| Evan Cheng | cd5731d | 2006-09-12 20:59:59 +0000 | [diff] [blame] | 1376 | // FIXME: add support to lower machine constant pool values into bytes! | 
| Torok Edwin | 7d696d8 | 2009-07-11 13:10:19 +0000 | [diff] [blame] | 1377 | llvm_report_error("Initialize memory with machine specific constant pool" | 
|  | 1378 | "entry has not been implemented!"); | 
| Evan Cheng | cd5731d | 2006-09-12 20:59:59 +0000 | [diff] [blame] | 1379 | } | 
| Evan Cheng | 1606e8e | 2009-03-13 07:51:59 +0000 | [diff] [blame] | 1380 | TheJIT->InitializeMemory(CPE.Val.ConstVal, (void*)CAddr); | 
| Chris Lattner | bbbfa99 | 2009-08-23 06:35:02 +0000 | [diff] [blame] | 1381 | DEBUG(errs() << "JIT:   CP" << i << " at [0x"; | 
|  | 1382 | errs().write_hex(CAddr) << "]\n"); | 
| Evan Cheng | 1606e8e | 2009-03-13 07:51:59 +0000 | [diff] [blame] | 1383 |  | 
|  | 1384 | const Type *Ty = CPE.Val.ConstVal->getType(); | 
| Duncan Sands | 777d230 | 2009-05-09 07:06:46 +0000 | [diff] [blame] | 1385 | Offset += TheJIT->getTargetData()->getTypeAllocSize(Ty); | 
| Chris Lattner | 1cc0838 | 2003-01-13 01:00:12 +0000 | [diff] [blame] | 1386 | } | 
|  | 1387 | } | 
|  | 1388 |  | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1389 | void JITEmitter::initJumpTableInfo(MachineJumpTableInfo *MJTI) { | 
| Evan Cheng | 47c01a0 | 2008-11-07 09:02:17 +0000 | [diff] [blame] | 1390 | if (TheJIT->getJITInfo().hasCustomJumpTables()) | 
|  | 1391 | return; | 
|  | 1392 |  | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1393 | const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); | 
|  | 1394 | if (JT.empty()) return; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1395 |  | 
| Chris Lattner | f75f9be | 2006-05-02 23:22:24 +0000 | [diff] [blame] | 1396 | unsigned NumEntries = 0; | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1397 | for (unsigned i = 0, e = JT.size(); i != e; ++i) | 
| Chris Lattner | f75f9be | 2006-05-02 23:22:24 +0000 | [diff] [blame] | 1398 | NumEntries += JT[i].MBBs.size(); | 
|  | 1399 |  | 
|  | 1400 | unsigned EntrySize = MJTI->getEntrySize(); | 
|  | 1401 |  | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1402 | // Just allocate space for all the jump tables now.  We will fix up the actual | 
|  | 1403 | // MBB entries in the tables after we emit the code for each block, since then | 
|  | 1404 | // we will know the final locations of the MBBs in memory. | 
|  | 1405 | JumpTable = MJTI; | 
| Chris Lattner | f75f9be | 2006-05-02 23:22:24 +0000 | [diff] [blame] | 1406 | JumpTableBase = allocateSpace(NumEntries * EntrySize, MJTI->getAlignment()); | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1407 | } | 
|  | 1408 |  | 
| Jim Laskey | b92767a | 2006-12-14 22:53:42 +0000 | [diff] [blame] | 1409 | void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { | 
| Evan Cheng | 47c01a0 | 2008-11-07 09:02:17 +0000 | [diff] [blame] | 1410 | if (TheJIT->getJITInfo().hasCustomJumpTables()) | 
|  | 1411 | return; | 
|  | 1412 |  | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1413 | const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); | 
| Chris Lattner | f75f9be | 2006-05-02 23:22:24 +0000 | [diff] [blame] | 1414 | if (JT.empty() || JumpTableBase == 0) return; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1415 |  | 
| Jim Laskey | b92767a | 2006-12-14 22:53:42 +0000 | [diff] [blame] | 1416 | if (TargetMachine::getRelocationModel() == Reloc::PIC_) { | 
| Jim Laskey | acd80ac | 2006-12-14 19:17:33 +0000 | [diff] [blame] | 1417 | assert(MJTI->getEntrySize() == 4 && "Cross JIT'ing?"); | 
|  | 1418 | // For each jump table, place the offset from the beginning of the table | 
|  | 1419 | // to the target address. | 
|  | 1420 | int *SlotPtr = (int*)JumpTableBase; | 
| Chris Lattner | 32ca55f | 2006-05-03 00:13:06 +0000 | [diff] [blame] | 1421 |  | 
| Jim Laskey | acd80ac | 2006-12-14 19:17:33 +0000 | [diff] [blame] | 1422 | for (unsigned i = 0, e = JT.size(); i != e; ++i) { | 
|  | 1423 | const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs; | 
|  | 1424 | // Store the offset of the basic block for this jump table slot in the | 
|  | 1425 | // memory we allocated for the jump table in 'initJumpTableInfo' | 
| Evan Cheng | 5788d1a | 2008-12-10 02:32:19 +0000 | [diff] [blame] | 1426 | uintptr_t Base = (uintptr_t)SlotPtr; | 
| Evan Cheng | 2a3e08b | 2008-01-05 02:26:58 +0000 | [diff] [blame] | 1427 | for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { | 
| Evan Cheng | 5788d1a | 2008-12-10 02:32:19 +0000 | [diff] [blame] | 1428 | uintptr_t MBBAddr = getMachineBasicBlockAddress(MBBs[mi]); | 
| Evan Cheng | 2a3e08b | 2008-01-05 02:26:58 +0000 | [diff] [blame] | 1429 | *SlotPtr++ = TheJIT->getJITInfo().getPICJumpTableEntry(MBBAddr, Base); | 
|  | 1430 | } | 
| Jim Laskey | acd80ac | 2006-12-14 19:17:33 +0000 | [diff] [blame] | 1431 | } | 
|  | 1432 | } else { | 
|  | 1433 | assert(MJTI->getEntrySize() == sizeof(void*) && "Cross JIT'ing?"); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1434 |  | 
|  | 1435 | // For each jump table, map each target in the jump table to the address of | 
| Jim Laskey | acd80ac | 2006-12-14 19:17:33 +0000 | [diff] [blame] | 1436 | // an emitted MachineBasicBlock. | 
|  | 1437 | intptr_t *SlotPtr = (intptr_t*)JumpTableBase; | 
|  | 1438 |  | 
|  | 1439 | for (unsigned i = 0, e = JT.size(); i != e; ++i) { | 
|  | 1440 | const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs; | 
|  | 1441 | // Store the address of the basic block for this jump table slot in the | 
|  | 1442 | // memory we allocated for the jump table in 'initJumpTableInfo' | 
|  | 1443 | for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) | 
|  | 1444 | *SlotPtr++ = getMachineBasicBlockAddress(MBBs[mi]); | 
|  | 1445 | } | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1446 | } | 
|  | 1447 | } | 
|  | 1448 |  | 
| Evan Cheng | ce4a70b | 2008-11-08 08:02:53 +0000 | [diff] [blame] | 1449 | void JITEmitter::startGVStub(const GlobalValue* GV, unsigned StubSize, | 
|  | 1450 | unsigned Alignment) { | 
| Chris Lattner | 43b429b | 2006-05-02 18:27:26 +0000 | [diff] [blame] | 1451 | SavedBufferBegin = BufferBegin; | 
|  | 1452 | SavedBufferEnd = BufferEnd; | 
|  | 1453 | SavedCurBufferPtr = CurBufferPtr; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1454 |  | 
| Evan Cheng | ce4a70b | 2008-11-08 08:02:53 +0000 | [diff] [blame] | 1455 | BufferBegin = CurBufferPtr = MemMgr->allocateStub(GV, StubSize, Alignment); | 
| Chris Lattner | 43b429b | 2006-05-02 18:27:26 +0000 | [diff] [blame] | 1456 | BufferEnd = BufferBegin+StubSize+1; | 
| Chris Lattner | 6125fdd | 2003-05-09 03:30:07 +0000 | [diff] [blame] | 1457 | } | 
|  | 1458 |  | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 1459 | void JITEmitter::startGVStub(const GlobalValue* GV, void *Buffer, | 
|  | 1460 | unsigned StubSize) { | 
|  | 1461 | SavedBufferBegin = BufferBegin; | 
|  | 1462 | SavedBufferEnd = BufferEnd; | 
|  | 1463 | SavedCurBufferPtr = CurBufferPtr; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1464 |  | 
| Bruno Cardoso Lopes | 186c670 | 2009-06-04 00:15:51 +0000 | [diff] [blame] | 1465 | BufferBegin = CurBufferPtr = (uint8_t *)Buffer; | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 1466 | BufferEnd = BufferBegin+StubSize+1; | 
|  | 1467 | } | 
|  | 1468 |  | 
| Evan Cheng | ce4a70b | 2008-11-08 08:02:53 +0000 | [diff] [blame] | 1469 | void *JITEmitter::finishGVStub(const GlobalValue* GV) { | 
| Chris Lattner | 43b429b | 2006-05-02 18:27:26 +0000 | [diff] [blame] | 1470 | NumBytes += getCurrentPCOffset(); | 
|  | 1471 | std::swap(SavedBufferBegin, BufferBegin); | 
|  | 1472 | BufferEnd = SavedBufferEnd; | 
|  | 1473 | CurBufferPtr = SavedCurBufferPtr; | 
|  | 1474 | return SavedBufferBegin; | 
| Chris Lattner | bba1b6d | 2003-06-01 23:24:36 +0000 | [diff] [blame] | 1475 | } | 
|  | 1476 |  | 
| Chris Lattner | bba1b6d | 2003-06-01 23:24:36 +0000 | [diff] [blame] | 1477 | // getConstantPoolEntryAddress - Return the address of the 'ConstantNum' entry | 
|  | 1478 | // in the constant pool that was last emitted with the 'emitConstantPool' | 
|  | 1479 | // method. | 
|  | 1480 | // | 
| Evan Cheng | 5788d1a | 2008-12-10 02:32:19 +0000 | [diff] [blame] | 1481 | uintptr_t JITEmitter::getConstantPoolEntryAddress(unsigned ConstantNum) const { | 
| Chris Lattner | 239862c | 2006-02-09 04:49:59 +0000 | [diff] [blame] | 1482 | assert(ConstantNum < ConstantPool->getConstants().size() && | 
| Misha Brukman | 3c94497 | 2005-04-22 04:08:30 +0000 | [diff] [blame] | 1483 | "Invalid ConstantPoolIndex!"); | 
| Evan Cheng | 1606e8e | 2009-03-13 07:51:59 +0000 | [diff] [blame] | 1484 | return ConstPoolAddresses[ConstantNum]; | 
| Chris Lattner | bba1b6d | 2003-06-01 23:24:36 +0000 | [diff] [blame] | 1485 | } | 
|  | 1486 |  | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1487 | // getJumpTableEntryAddress - Return the address of the JumpTable with index | 
|  | 1488 | // 'Index' in the jumpp table that was last initialized with 'initJumpTableInfo' | 
|  | 1489 | // | 
| Evan Cheng | 5788d1a | 2008-12-10 02:32:19 +0000 | [diff] [blame] | 1490 | uintptr_t JITEmitter::getJumpTableEntryAddress(unsigned Index) const { | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1491 | const std::vector<MachineJumpTableEntry> &JT = JumpTable->getJumpTables(); | 
|  | 1492 | assert(Index < JT.size() && "Invalid jump table index!"); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1493 |  | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1494 | unsigned Offset = 0; | 
|  | 1495 | unsigned EntrySize = JumpTable->getEntrySize(); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1496 |  | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1497 | for (unsigned i = 0; i < Index; ++i) | 
| Jim Laskey | acd80ac | 2006-12-14 19:17:33 +0000 | [diff] [blame] | 1498 | Offset += JT[i].MBBs.size(); | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1499 |  | 
| Jim Laskey | acd80ac | 2006-12-14 19:17:33 +0000 | [diff] [blame] | 1500 | Offset *= EntrySize; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1501 |  | 
| Evan Cheng | 5788d1a | 2008-12-10 02:32:19 +0000 | [diff] [blame] | 1502 | return (uintptr_t)((char *)JumpTableBase + Offset); | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1503 | } | 
|  | 1504 |  | 
| Jeffrey Yasskin | 7a9034c | 2009-10-27 00:03:05 +0000 | [diff] [blame] | 1505 | void JITEmitter::EmittedFunctionConfig::onDelete( | 
|  | 1506 | JITEmitter *Emitter, const Function *F) { | 
|  | 1507 | Emitter->deallocateMemForFunction(F); | 
|  | 1508 | } | 
|  | 1509 | void JITEmitter::EmittedFunctionConfig::onRAUW( | 
|  | 1510 | JITEmitter *, const Function*, const Function*) { | 
|  | 1511 | llvm_unreachable("The JIT doesn't know how to handle a" | 
|  | 1512 | " RAUW on a value it has emitted."); | 
|  | 1513 | } | 
|  | 1514 |  | 
|  | 1515 |  | 
| Chris Lattner | e993cc2 | 2006-05-11 23:08:08 +0000 | [diff] [blame] | 1516 | //===----------------------------------------------------------------------===// | 
|  | 1517 | //  Public interface to this file | 
|  | 1518 | //===----------------------------------------------------------------------===// | 
|  | 1519 |  | 
| Reid Kleckner | 2763217 | 2009-09-20 23:52:43 +0000 | [diff] [blame] | 1520 | JITCodeEmitter *JIT::createEmitter(JIT &jit, JITMemoryManager *JMM, | 
|  | 1521 | TargetMachine &tm) { | 
|  | 1522 | return new JITEmitter(jit, JMM, tm); | 
| Chris Lattner | e993cc2 | 2006-05-11 23:08:08 +0000 | [diff] [blame] | 1523 | } | 
|  | 1524 |  | 
| Misha Brukman | d69c1e6 | 2003-07-28 19:09:06 +0000 | [diff] [blame] | 1525 | // getPointerToNamedFunction - This function is used as a global wrapper to | 
| Chris Lattner | 4d326fa | 2003-12-20 01:46:27 +0000 | [diff] [blame] | 1526 | // JIT::getPointerToNamedFunction for the purpose of resolving symbols when | 
| Misha Brukman | d69c1e6 | 2003-07-28 19:09:06 +0000 | [diff] [blame] | 1527 | // bugpoint is debugging the JIT. In that scenario, we are loading an .so and | 
|  | 1528 | // need to resolve function(s) that are being mis-codegenerated, so we need to | 
|  | 1529 | // resolve their addresses at runtime, and this is the way to do it. | 
|  | 1530 | extern "C" { | 
|  | 1531 | void *getPointerToNamedFunction(const char *Name) { | 
| Chris Lattner | fe85403 | 2006-08-16 01:24:12 +0000 | [diff] [blame] | 1532 | if (Function *F = TheJIT->FindFunctionNamed(Name)) | 
| Chris Lattner | 4d326fa | 2003-12-20 01:46:27 +0000 | [diff] [blame] | 1533 | return TheJIT->getPointerToFunction(F); | 
|  | 1534 | return TheJIT->getPointerToNamedFunction(Name); | 
| Misha Brukman | d69c1e6 | 2003-07-28 19:09:06 +0000 | [diff] [blame] | 1535 | } | 
|  | 1536 | } | 
| Chris Lattner | e993cc2 | 2006-05-11 23:08:08 +0000 | [diff] [blame] | 1537 |  | 
|  | 1538 | // getPointerToFunctionOrStub - If the specified function has been | 
|  | 1539 | // code-gen'd, return a pointer to the function.  If not, compile it, or use | 
|  | 1540 | // a stub to implement lazy compilation if available. | 
|  | 1541 | // | 
|  | 1542 | void *JIT::getPointerToFunctionOrStub(Function *F) { | 
|  | 1543 | // If we have already code generated the function, just return the address. | 
|  | 1544 | if (void *Addr = getPointerToGlobalIfAvailable(F)) | 
|  | 1545 | return Addr; | 
| Eric Christopher | 116664a | 2009-11-12 03:12:18 +0000 | [diff] [blame^] | 1546 |  | 
| Chris Lattner | e748401 | 2007-02-24 02:57:03 +0000 | [diff] [blame] | 1547 | // Get a stub if the target supports it. | 
| Bruno Cardoso Lopes | a3f99f9 | 2009-05-30 20:51:52 +0000 | [diff] [blame] | 1548 | assert(isa<JITEmitter>(JCE) && "Unexpected MCE?"); | 
| Evan Cheng | a044dfc | 2008-08-20 00:28:12 +0000 | [diff] [blame] | 1549 | JITEmitter *JE = cast<JITEmitter>(getCodeEmitter()); | 
| Chris Lattner | e748401 | 2007-02-24 02:57:03 +0000 | [diff] [blame] | 1550 | return JE->getJITResolver().getFunctionStub(F); | 
| Chris Lattner | e993cc2 | 2006-05-11 23:08:08 +0000 | [diff] [blame] | 1551 | } | 
|  | 1552 |  | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 1553 | void JIT::updateFunctionStub(Function *F) { | 
|  | 1554 | // Get the empty stub we generated earlier. | 
| Bruno Cardoso Lopes | a3f99f9 | 2009-05-30 20:51:52 +0000 | [diff] [blame] | 1555 | assert(isa<JITEmitter>(JCE) && "Unexpected MCE?"); | 
| Nate Begeman | d6b7a24 | 2009-02-18 08:31:02 +0000 | [diff] [blame] | 1556 | JITEmitter *JE = cast<JITEmitter>(getCodeEmitter()); | 
|  | 1557 | void *Stub = JE->getJITResolver().getFunctionStub(F); | 
|  | 1558 |  | 
|  | 1559 | // Tell the target jit info to rewrite the stub at the specified address, | 
|  | 1560 | // rather than creating a new one. | 
|  | 1561 | void *Addr = getPointerToGlobalIfAvailable(F); | 
|  | 1562 | getJITInfo().emitFunctionStubAtAddr(F, Addr, Stub, *getCodeEmitter()); | 
|  | 1563 | } | 
|  | 1564 |  | 
| Chris Lattner | e993cc2 | 2006-05-11 23:08:08 +0000 | [diff] [blame] | 1565 | /// freeMachineCodeForFunction - release machine code memory for given Function. | 
|  | 1566 | /// | 
|  | 1567 | void JIT::freeMachineCodeForFunction(Function *F) { | 
|  | 1568 | // Delete translation for this from the ExecutionEngine, so it will get | 
|  | 1569 | // retranslated next time it is used. | 
| Jeffrey Yasskin | 7a9034c | 2009-10-27 00:03:05 +0000 | [diff] [blame] | 1570 | updateGlobalMapping(F, 0); | 
| Chris Lattner | e993cc2 | 2006-05-11 23:08:08 +0000 | [diff] [blame] | 1571 |  | 
|  | 1572 | // Free the actual memory for the function body and related stuff. | 
| Bruno Cardoso Lopes | a3f99f9 | 2009-05-30 20:51:52 +0000 | [diff] [blame] | 1573 | assert(isa<JITEmitter>(JCE) && "Unexpected MCE?"); | 
|  | 1574 | cast<JITEmitter>(JCE)->deallocateMemForFunction(F); | 
| Chris Lattner | e993cc2 | 2006-05-11 23:08:08 +0000 | [diff] [blame] | 1575 | } |