1 //===---- OrcMCJITReplacement.h - Orc based MCJIT replacement ---*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Orc based MCJIT replacement. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H 15 #define LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H 16 17 #include "llvm/ExecutionEngine/ExecutionEngine.h" 18 #include "llvm/ExecutionEngine/Orc/CompileUtils.h" 19 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" 20 #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" 21 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" 22 #include "llvm/Object/Archive.h" 23 24 namespace llvm { 25 namespace orc { 26 27 class OrcMCJITReplacement : public ExecutionEngine { 28 29 // OrcMCJITReplacement needs to do a little extra book-keeping to ensure that 30 // Orc's automatic finalization doesn't kick in earlier than MCJIT clients are 31 // expecting - see finalizeMemory. 32 class MCJITReplacementMemMgr : public MCJITMemoryManager { 33 public: MCJITReplacementMemMgr(OrcMCJITReplacement & M,std::shared_ptr<MCJITMemoryManager> ClientMM)34 MCJITReplacementMemMgr(OrcMCJITReplacement &M, 35 std::shared_ptr<MCJITMemoryManager> ClientMM) 36 : M(M), ClientMM(std::move(ClientMM)) {} 37 allocateCodeSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,StringRef SectionName)38 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, 39 unsigned SectionID, 40 StringRef SectionName) override { 41 uint8_t *Addr = 42 ClientMM->allocateCodeSection(Size, Alignment, SectionID, 43 SectionName); 44 M.SectionsAllocatedSinceLastLoad.insert(Addr); 45 return Addr; 46 } 47 allocateDataSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,StringRef SectionName,bool IsReadOnly)48 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, 49 unsigned SectionID, StringRef SectionName, 50 bool IsReadOnly) override { 51 uint8_t *Addr = ClientMM->allocateDataSection(Size, Alignment, SectionID, 52 SectionName, IsReadOnly); 53 M.SectionsAllocatedSinceLastLoad.insert(Addr); 54 return Addr; 55 } 56 reserveAllocationSpace(uintptr_t CodeSize,uint32_t CodeAlign,uintptr_t RODataSize,uint32_t RODataAlign,uintptr_t RWDataSize,uint32_t RWDataAlign)57 void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, 58 uintptr_t RODataSize, uint32_t RODataAlign, 59 uintptr_t RWDataSize, 60 uint32_t RWDataAlign) override { 61 return ClientMM->reserveAllocationSpace(CodeSize, CodeAlign, 62 RODataSize, RODataAlign, 63 RWDataSize, RWDataAlign); 64 } 65 needsToReserveAllocationSpace()66 bool needsToReserveAllocationSpace() override { 67 return ClientMM->needsToReserveAllocationSpace(); 68 } 69 registerEHFrames(uint8_t * Addr,uint64_t LoadAddr,size_t Size)70 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, 71 size_t Size) override { 72 return ClientMM->registerEHFrames(Addr, LoadAddr, Size); 73 } 74 deregisterEHFrames(uint8_t * Addr,uint64_t LoadAddr,size_t Size)75 void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, 76 size_t Size) override { 77 return ClientMM->deregisterEHFrames(Addr, LoadAddr, Size); 78 } 79 notifyObjectLoaded(RuntimeDyld & RTDyld,const object::ObjectFile & O)80 void notifyObjectLoaded(RuntimeDyld &RTDyld, 81 const object::ObjectFile &O) override { 82 return ClientMM->notifyObjectLoaded(RTDyld, O); 83 } 84 notifyObjectLoaded(ExecutionEngine * EE,const object::ObjectFile & O)85 void notifyObjectLoaded(ExecutionEngine *EE, 86 const object::ObjectFile &O) override { 87 return ClientMM->notifyObjectLoaded(EE, O); 88 } 89 90 bool finalizeMemory(std::string *ErrMsg = nullptr) override { 91 // Each set of objects loaded will be finalized exactly once, but since 92 // symbol lookup during relocation may recursively trigger the 93 // loading/relocation of other modules, and since we're forwarding all 94 // finalizeMemory calls to a single underlying memory manager, we need to 95 // defer forwarding the call on until all necessary objects have been 96 // loaded. Otherwise, during the relocation of a leaf object, we will end 97 // up finalizing memory, causing a crash further up the stack when we 98 // attempt to apply relocations to finalized memory. 99 // To avoid finalizing too early, look at how many objects have been 100 // loaded but not yet finalized. This is a bit of a hack that relies on 101 // the fact that we're lazily emitting object files: The only way you can 102 // get more than one set of objects loaded but not yet finalized is if 103 // they were loaded during relocation of another set. 104 if (M.UnfinalizedSections.size() == 1) 105 return ClientMM->finalizeMemory(ErrMsg); 106 return false; 107 } 108 109 private: 110 OrcMCJITReplacement &M; 111 std::shared_ptr<MCJITMemoryManager> ClientMM; 112 }; 113 114 class LinkingResolver : public RuntimeDyld::SymbolResolver { 115 public: LinkingResolver(OrcMCJITReplacement & M)116 LinkingResolver(OrcMCJITReplacement &M) : M(M) {} 117 findSymbol(const std::string & Name)118 RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override { 119 return M.findMangledSymbol(Name); 120 } 121 122 RuntimeDyld::SymbolInfo findSymbolInLogicalDylib(const std::string & Name)123 findSymbolInLogicalDylib(const std::string &Name) override { 124 return M.ClientResolver->findSymbol(Name); 125 } 126 127 private: 128 OrcMCJITReplacement &M; 129 }; 130 131 private: 132 133 static ExecutionEngine * createOrcMCJITReplacement(std::string * ErrorMsg,std::shared_ptr<MCJITMemoryManager> MemMgr,std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver,std::unique_ptr<TargetMachine> TM)134 createOrcMCJITReplacement(std::string *ErrorMsg, 135 std::shared_ptr<MCJITMemoryManager> MemMgr, 136 std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver, 137 std::unique_ptr<TargetMachine> TM) { 138 return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver), 139 std::move(TM)); 140 } 141 142 public: Register()143 static void Register() { 144 OrcMCJITReplacementCtor = createOrcMCJITReplacement; 145 } 146 OrcMCJITReplacement(std::shared_ptr<MCJITMemoryManager> MemMgr,std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver,std::unique_ptr<TargetMachine> TM)147 OrcMCJITReplacement( 148 std::shared_ptr<MCJITMemoryManager> MemMgr, 149 std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver, 150 std::unique_ptr<TargetMachine> TM) 151 : ExecutionEngine(TM->createDataLayout()), TM(std::move(TM)), 152 MemMgr(*this, std::move(MemMgr)), Resolver(*this), 153 ClientResolver(std::move(ClientResolver)), NotifyObjectLoaded(*this), 154 NotifyFinalized(*this), 155 ObjectLayer(NotifyObjectLoaded, NotifyFinalized), 156 CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)), 157 LazyEmitLayer(CompileLayer) {} 158 addModule(std::unique_ptr<Module> M)159 void addModule(std::unique_ptr<Module> M) override { 160 161 // If this module doesn't have a DataLayout attached then attach the 162 // default. 163 if (M->getDataLayout().isDefault()) { 164 M->setDataLayout(getDataLayout()); 165 } else { 166 assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch"); 167 } 168 Modules.push_back(std::move(M)); 169 std::vector<Module *> Ms; 170 Ms.push_back(&*Modules.back()); 171 LazyEmitLayer.addModuleSet(std::move(Ms), &MemMgr, &Resolver); 172 } 173 addObjectFile(std::unique_ptr<object::ObjectFile> O)174 void addObjectFile(std::unique_ptr<object::ObjectFile> O) override { 175 std::vector<std::unique_ptr<object::ObjectFile>> Objs; 176 Objs.push_back(std::move(O)); 177 ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver); 178 } 179 addObjectFile(object::OwningBinary<object::ObjectFile> O)180 void addObjectFile(object::OwningBinary<object::ObjectFile> O) override { 181 std::vector<std::unique_ptr<object::OwningBinary<object::ObjectFile>>> Objs; 182 Objs.push_back( 183 llvm::make_unique<object::OwningBinary<object::ObjectFile>>( 184 std::move(O))); 185 ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver); 186 } 187 addArchive(object::OwningBinary<object::Archive> A)188 void addArchive(object::OwningBinary<object::Archive> A) override { 189 Archives.push_back(std::move(A)); 190 } 191 getSymbolAddress(StringRef Name)192 uint64_t getSymbolAddress(StringRef Name) { 193 return findSymbol(Name).getAddress(); 194 } 195 findSymbol(StringRef Name)196 RuntimeDyld::SymbolInfo findSymbol(StringRef Name) { 197 return findMangledSymbol(Mangle(Name)); 198 } 199 finalizeObject()200 void finalizeObject() override { 201 // This is deprecated - Aim to remove in ExecutionEngine. 202 // REMOVE IF POSSIBLE - Doesn't make sense for New JIT. 203 } 204 mapSectionAddress(const void * LocalAddress,uint64_t TargetAddress)205 void mapSectionAddress(const void *LocalAddress, 206 uint64_t TargetAddress) override { 207 for (auto &P : UnfinalizedSections) 208 if (P.second.count(LocalAddress)) 209 ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress); 210 } 211 getGlobalValueAddress(const std::string & Name)212 uint64_t getGlobalValueAddress(const std::string &Name) override { 213 return getSymbolAddress(Name); 214 } 215 getFunctionAddress(const std::string & Name)216 uint64_t getFunctionAddress(const std::string &Name) override { 217 return getSymbolAddress(Name); 218 } 219 getPointerToFunction(Function * F)220 void *getPointerToFunction(Function *F) override { 221 uint64_t FAddr = getSymbolAddress(F->getName()); 222 return reinterpret_cast<void *>(static_cast<uintptr_t>(FAddr)); 223 } 224 225 void *getPointerToNamedFunction(StringRef Name, 226 bool AbortOnFailure = true) override { 227 uint64_t Addr = getSymbolAddress(Name); 228 if (!Addr && AbortOnFailure) 229 llvm_unreachable("Missing symbol!"); 230 return reinterpret_cast<void *>(static_cast<uintptr_t>(Addr)); 231 } 232 233 GenericValue runFunction(Function *F, 234 ArrayRef<GenericValue> ArgValues) override; 235 setObjectCache(ObjectCache * NewCache)236 void setObjectCache(ObjectCache *NewCache) override { 237 CompileLayer.setObjectCache(NewCache); 238 } 239 setProcessAllSections(bool ProcessAllSections)240 void setProcessAllSections(bool ProcessAllSections) override { 241 ObjectLayer.setProcessAllSections(ProcessAllSections); 242 } 243 244 private: 245 findMangledSymbol(StringRef Name)246 RuntimeDyld::SymbolInfo findMangledSymbol(StringRef Name) { 247 if (auto Sym = LazyEmitLayer.findSymbol(Name, false)) 248 return Sym.toRuntimeDyldSymbol(); 249 if (auto Sym = ClientResolver->findSymbol(Name)) 250 return Sym; 251 if (auto Sym = scanArchives(Name)) 252 return Sym.toRuntimeDyldSymbol(); 253 254 return nullptr; 255 } 256 scanArchives(StringRef Name)257 JITSymbol scanArchives(StringRef Name) { 258 for (object::OwningBinary<object::Archive> &OB : Archives) { 259 object::Archive *A = OB.getBinary(); 260 // Look for our symbols in each Archive 261 auto OptionalChildOrErr = A->findSym(Name); 262 if (!OptionalChildOrErr) 263 report_fatal_error(OptionalChildOrErr.takeError()); 264 auto &OptionalChild = *OptionalChildOrErr; 265 if (OptionalChild) { 266 // FIXME: Support nested archives? 267 Expected<std::unique_ptr<object::Binary>> ChildBinOrErr = 268 OptionalChild->getAsBinary(); 269 if (!ChildBinOrErr) { 270 // TODO: Actually report errors helpfully. 271 consumeError(ChildBinOrErr.takeError()); 272 continue; 273 } 274 std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get(); 275 if (ChildBin->isObject()) { 276 std::vector<std::unique_ptr<object::ObjectFile>> ObjSet; 277 ObjSet.push_back(std::unique_ptr<object::ObjectFile>( 278 static_cast<object::ObjectFile *>(ChildBin.release()))); 279 ObjectLayer.addObjectSet(std::move(ObjSet), &MemMgr, &Resolver); 280 if (auto Sym = ObjectLayer.findSymbol(Name, true)) 281 return Sym; 282 } 283 } 284 } 285 return nullptr; 286 } 287 288 class NotifyObjectLoadedT { 289 public: 290 typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>> 291 LoadedObjInfoListT; 292 NotifyObjectLoadedT(OrcMCJITReplacement & M)293 NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {} 294 295 template <typename ObjListT> operator()296 void operator()(ObjectLinkingLayerBase::ObjSetHandleT H, 297 const ObjListT &Objects, 298 const LoadedObjInfoListT &Infos) const { 299 M.UnfinalizedSections[H] = std::move(M.SectionsAllocatedSinceLastLoad); 300 M.SectionsAllocatedSinceLastLoad = SectionAddrSet(); 301 assert(Objects.size() == Infos.size() && 302 "Incorrect number of Infos for Objects."); 303 for (unsigned I = 0; I < Objects.size(); ++I) 304 M.MemMgr.notifyObjectLoaded(&M, getObject(*Objects[I])); 305 } 306 307 private: 308 getObject(const object::ObjectFile & Obj)309 static const object::ObjectFile& getObject(const object::ObjectFile &Obj) { 310 return Obj; 311 } 312 313 template <typename ObjT> 314 static const object::ObjectFile& getObject(const object::OwningBinary<ObjT> & Obj)315 getObject(const object::OwningBinary<ObjT> &Obj) { 316 return *Obj.getBinary(); 317 } 318 319 OrcMCJITReplacement &M; 320 }; 321 322 class NotifyFinalizedT { 323 public: NotifyFinalizedT(OrcMCJITReplacement & M)324 NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {} operator()325 void operator()(ObjectLinkingLayerBase::ObjSetHandleT H) { 326 M.UnfinalizedSections.erase(H); 327 } 328 329 private: 330 OrcMCJITReplacement &M; 331 }; 332 Mangle(StringRef Name)333 std::string Mangle(StringRef Name) { 334 std::string MangledName; 335 { 336 raw_string_ostream MangledNameStream(MangledName); 337 Mang.getNameWithPrefix(MangledNameStream, Name, getDataLayout()); 338 } 339 return MangledName; 340 } 341 342 typedef ObjectLinkingLayer<NotifyObjectLoadedT> ObjectLayerT; 343 typedef IRCompileLayer<ObjectLayerT> CompileLayerT; 344 typedef LazyEmittingLayer<CompileLayerT> LazyEmitLayerT; 345 346 std::unique_ptr<TargetMachine> TM; 347 MCJITReplacementMemMgr MemMgr; 348 LinkingResolver Resolver; 349 std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver; 350 Mangler Mang; 351 352 NotifyObjectLoadedT NotifyObjectLoaded; 353 NotifyFinalizedT NotifyFinalized; 354 355 ObjectLayerT ObjectLayer; 356 CompileLayerT CompileLayer; 357 LazyEmitLayerT LazyEmitLayer; 358 359 // We need to store ObjLayerT::ObjSetHandles for each of the object sets 360 // that have been emitted but not yet finalized so that we can forward the 361 // mapSectionAddress calls appropriately. 362 typedef std::set<const void *> SectionAddrSet; 363 struct ObjSetHandleCompare { operatorObjSetHandleCompare364 bool operator()(ObjectLayerT::ObjSetHandleT H1, 365 ObjectLayerT::ObjSetHandleT H2) const { 366 return &*H1 < &*H2; 367 } 368 }; 369 SectionAddrSet SectionsAllocatedSinceLastLoad; 370 std::map<ObjectLayerT::ObjSetHandleT, SectionAddrSet, ObjSetHandleCompare> 371 UnfinalizedSections; 372 373 std::vector<object::OwningBinary<object::Archive>> Archives; 374 }; 375 376 } // End namespace orc. 377 } // End namespace llvm. 378 379 #endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H 380