OrcCBindingsStack.h revision 360784
1//===- OrcCBindingsStack.h - Orc JIT stack for C bindings -----*- C++ -*---===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H 10#define LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H 11 12#include "llvm-c/OrcBindings.h" 13#include "llvm-c/TargetMachine.h" 14#include "llvm/ADT/STLExtras.h" 15#include "llvm/ADT/StringRef.h" 16#include "llvm/ExecutionEngine/JITSymbol.h" 17#include "llvm/ExecutionEngine/JITEventListener.h" 18#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" 19#include "llvm/ExecutionEngine/Orc/CompileUtils.h" 20#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 21#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" 22#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" 23#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" 24#include "llvm/ExecutionEngine/RuntimeDyld.h" 25#include "llvm/ExecutionEngine/SectionMemoryManager.h" 26#include "llvm/IR/DataLayout.h" 27#include "llvm/IR/Mangler.h" 28#include "llvm/IR/Module.h" 29#include "llvm/Support/CBindingWrapping.h" 30#include "llvm/Support/Error.h" 31#include "llvm/Support/raw_ostream.h" 32#include "llvm/Target/TargetMachine.h" 33#include <algorithm> 34#include <cstdint> 35#include <functional> 36#include <map> 37#include <memory> 38#include <set> 39#include <string> 40#include <vector> 41 42namespace llvm { 43 44class OrcCBindingsStack; 45 46DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef) 47DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) 48 49namespace detail { 50 51// FIXME: Kill this off once the Layer concept becomes an interface. 52class GenericLayer { 53public: 54 virtual ~GenericLayer() = default; 55 56 virtual JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name, 57 bool ExportedSymbolsOnly) = 0; 58 virtual Error removeModule(orc::VModuleKey K) = 0; 59 }; 60 61 template <typename LayerT> class GenericLayerImpl : public GenericLayer { 62 public: 63 GenericLayerImpl(LayerT &Layer) : Layer(Layer) {} 64 65 JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name, 66 bool ExportedSymbolsOnly) override { 67 return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly); 68 } 69 70 Error removeModule(orc::VModuleKey K) override { 71 return Layer.removeModule(K); 72 } 73 74 private: 75 LayerT &Layer; 76 }; 77 78 template <> 79 class GenericLayerImpl<orc::LegacyRTDyldObjectLinkingLayer> : public GenericLayer { 80 private: 81 using LayerT = orc::LegacyRTDyldObjectLinkingLayer; 82 public: 83 GenericLayerImpl(LayerT &Layer) : Layer(Layer) {} 84 85 JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name, 86 bool ExportedSymbolsOnly) override { 87 return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly); 88 } 89 90 Error removeModule(orc::VModuleKey K) override { 91 return Layer.removeObject(K); 92 } 93 94 private: 95 LayerT &Layer; 96 }; 97 98 template <typename LayerT> 99 std::unique_ptr<GenericLayerImpl<LayerT>> createGenericLayer(LayerT &Layer) { 100 return std::make_unique<GenericLayerImpl<LayerT>>(Layer); 101 } 102 103} // end namespace detail 104 105class OrcCBindingsStack { 106public: 107 108 using CompileCallbackMgr = orc::JITCompileCallbackManager; 109 using ObjLayerT = orc::LegacyRTDyldObjectLinkingLayer; 110 using CompileLayerT = orc::LegacyIRCompileLayer<ObjLayerT, orc::SimpleCompiler>; 111 using CODLayerT = 112 orc::LegacyCompileOnDemandLayer<CompileLayerT, CompileCallbackMgr>; 113 114 using CallbackManagerBuilder = 115 std::function<std::unique_ptr<CompileCallbackMgr>()>; 116 117 using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT; 118 119private: 120 121 using OwningObject = object::OwningBinary<object::ObjectFile>; 122 123 class CBindingsResolver : public orc::SymbolResolver { 124 public: 125 CBindingsResolver(OrcCBindingsStack &Stack, 126 LLVMOrcSymbolResolverFn ExternalResolver, 127 void *ExternalResolverCtx) 128 : Stack(Stack), ExternalResolver(std::move(ExternalResolver)), 129 ExternalResolverCtx(std::move(ExternalResolverCtx)) {} 130 131 orc::SymbolNameSet 132 getResponsibilitySet(const orc::SymbolNameSet &Symbols) override { 133 orc::SymbolNameSet Result; 134 135 for (auto &S : Symbols) { 136 if (auto Sym = findSymbol(*S)) { 137 if (!Sym.getFlags().isStrong()) 138 Result.insert(S); 139 } else if (auto Err = Sym.takeError()) { 140 Stack.reportError(std::move(Err)); 141 return orc::SymbolNameSet(); 142 } 143 } 144 145 return Result; 146 } 147 148 orc::SymbolNameSet 149 lookup(std::shared_ptr<orc::AsynchronousSymbolQuery> Query, 150 orc::SymbolNameSet Symbols) override { 151 orc::SymbolNameSet UnresolvedSymbols; 152 153 for (auto &S : Symbols) { 154 if (auto Sym = findSymbol(*S)) { 155 if (auto Addr = Sym.getAddress()) { 156 Query->notifySymbolMetRequiredState( 157 S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); 158 } else { 159 Stack.ES.legacyFailQuery(*Query, Addr.takeError()); 160 return orc::SymbolNameSet(); 161 } 162 } else if (auto Err = Sym.takeError()) { 163 Stack.ES.legacyFailQuery(*Query, std::move(Err)); 164 return orc::SymbolNameSet(); 165 } else 166 UnresolvedSymbols.insert(S); 167 } 168 169 if (Query->isComplete()) 170 Query->handleComplete(); 171 172 return UnresolvedSymbols; 173 } 174 175 private: 176 JITSymbol findSymbol(const std::string &Name) { 177 // Search order: 178 // 1. JIT'd symbols. 179 // 2. Runtime overrides. 180 // 3. External resolver (if present). 181 182 if (Stack.CODLayer) { 183 if (auto Sym = Stack.CODLayer->findSymbol(Name, true)) 184 return Sym; 185 else if (auto Err = Sym.takeError()) 186 return Sym.takeError(); 187 } else { 188 if (auto Sym = Stack.CompileLayer.findSymbol(Name, true)) 189 return Sym; 190 else if (auto Err = Sym.takeError()) 191 return Sym.takeError(); 192 } 193 194 if (auto Sym = Stack.CXXRuntimeOverrides.searchOverrides(Name)) 195 return Sym; 196 197 if (ExternalResolver) 198 return JITSymbol(ExternalResolver(Name.c_str(), ExternalResolverCtx), 199 JITSymbolFlags::Exported); 200 201 return JITSymbol(nullptr); 202 } 203 204 OrcCBindingsStack &Stack; 205 LLVMOrcSymbolResolverFn ExternalResolver; 206 void *ExternalResolverCtx = nullptr; 207 }; 208 209public: 210 OrcCBindingsStack(TargetMachine &TM, 211 IndirectStubsManagerBuilder IndirectStubsMgrBuilder) 212 : CCMgr(createCompileCallbackManager(TM, ES)), DL(TM.createDataLayout()), 213 IndirectStubsMgr(IndirectStubsMgrBuilder()), 214 ObjectLayer( 215 AcknowledgeORCv1Deprecation, ES, 216 [this](orc::VModuleKey K) { 217 auto ResolverI = Resolvers.find(K); 218 assert(ResolverI != Resolvers.end() && 219 "No resolver for module K"); 220 auto Resolver = std::move(ResolverI->second); 221 Resolvers.erase(ResolverI); 222 return ObjLayerT::Resources{ 223 std::make_shared<SectionMemoryManager>(), Resolver}; 224 }, 225 nullptr, 226 [this](orc::VModuleKey K, const object::ObjectFile &Obj, 227 const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) { 228 this->notifyFinalized(K, Obj, LoadedObjInfo); 229 }, 230 [this](orc::VModuleKey K, const object::ObjectFile &Obj) { 231 this->notifyFreed(K, Obj); 232 }), 233 CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer, 234 orc::SimpleCompiler(TM)), 235 CODLayer(createCODLayer(ES, CompileLayer, CCMgr.get(), 236 std::move(IndirectStubsMgrBuilder), Resolvers)), 237 CXXRuntimeOverrides( 238 AcknowledgeORCv1Deprecation, 239 [this](const std::string &S) { return mangle(S); }) {} 240 241 Error shutdown() { 242 // Run any destructors registered with __cxa_atexit. 243 CXXRuntimeOverrides.runDestructors(); 244 // Run any IR destructors. 245 for (auto &DtorRunner : IRStaticDestructorRunners) 246 if (auto Err = DtorRunner.runViaLayer(*this)) 247 return Err; 248 return Error::success(); 249 } 250 251 std::string mangle(StringRef Name) { 252 std::string MangledName; 253 { 254 raw_string_ostream MangledNameStream(MangledName); 255 Mangler::getNameWithPrefix(MangledNameStream, Name, DL); 256 } 257 return MangledName; 258 } 259 260 template <typename PtrTy> 261 static PtrTy fromTargetAddress(JITTargetAddress Addr) { 262 return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr)); 263 } 264 265 Expected<JITTargetAddress> 266 createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback, 267 void *CallbackCtx) { 268 auto WrappedCallback = [=]() -> JITTargetAddress { 269 return Callback(wrap(this), CallbackCtx); 270 }; 271 272 return CCMgr->getCompileCallback(std::move(WrappedCallback)); 273 } 274 275 Error createIndirectStub(StringRef StubName, JITTargetAddress Addr) { 276 return IndirectStubsMgr->createStub(StubName, Addr, 277 JITSymbolFlags::Exported); 278 } 279 280 Error setIndirectStubPointer(StringRef Name, JITTargetAddress Addr) { 281 return IndirectStubsMgr->updatePointer(Name, Addr); 282 } 283 284 template <typename LayerT> 285 Expected<orc::VModuleKey> 286 addIRModule(LayerT &Layer, std::unique_ptr<Module> M, 287 std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr, 288 LLVMOrcSymbolResolverFn ExternalResolver, 289 void *ExternalResolverCtx) { 290 291 // Attach a data-layout if one isn't already present. 292 if (M->getDataLayout().isDefault()) 293 M->setDataLayout(DL); 294 295 // Record the static constructors and destructors. We have to do this before 296 // we hand over ownership of the module to the JIT. 297 std::vector<std::string> CtorNames, DtorNames; 298 for (auto Ctor : orc::getConstructors(*M)) 299 CtorNames.push_back(mangle(Ctor.Func->getName())); 300 for (auto Dtor : orc::getDestructors(*M)) 301 DtorNames.push_back(mangle(Dtor.Func->getName())); 302 303 // Add the module to the JIT. 304 auto K = ES.allocateVModule(); 305 Resolvers[K] = std::make_shared<CBindingsResolver>(*this, ExternalResolver, 306 ExternalResolverCtx); 307 if (auto Err = Layer.addModule(K, std::move(M))) 308 return std::move(Err); 309 310 KeyLayers[K] = detail::createGenericLayer(Layer); 311 312 // Run the static constructors, and save the static destructor runner for 313 // execution when the JIT is torn down. 314 orc::LegacyCtorDtorRunner<OrcCBindingsStack> CtorRunner( 315 AcknowledgeORCv1Deprecation, std::move(CtorNames), K); 316 if (auto Err = CtorRunner.runViaLayer(*this)) 317 return std::move(Err); 318 319 IRStaticDestructorRunners.emplace_back(AcknowledgeORCv1Deprecation, 320 std::move(DtorNames), K); 321 322 return K; 323 } 324 325 Expected<orc::VModuleKey> 326 addIRModuleEager(std::unique_ptr<Module> M, 327 LLVMOrcSymbolResolverFn ExternalResolver, 328 void *ExternalResolverCtx) { 329 return addIRModule(CompileLayer, std::move(M), 330 std::make_unique<SectionMemoryManager>(), 331 std::move(ExternalResolver), ExternalResolverCtx); 332 } 333 334 Expected<orc::VModuleKey> 335 addIRModuleLazy(std::unique_ptr<Module> M, 336 LLVMOrcSymbolResolverFn ExternalResolver, 337 void *ExternalResolverCtx) { 338 if (!CODLayer) 339 return make_error<StringError>("Can not add lazy module: No compile " 340 "callback manager available", 341 inconvertibleErrorCode()); 342 343 return addIRModule(*CODLayer, std::move(M), 344 std::make_unique<SectionMemoryManager>(), 345 std::move(ExternalResolver), ExternalResolverCtx); 346 } 347 348 Error removeModule(orc::VModuleKey K) { 349 // FIXME: Should error release the module key? 350 if (auto Err = KeyLayers[K]->removeModule(K)) 351 return Err; 352 ES.releaseVModule(K); 353 KeyLayers.erase(K); 354 return Error::success(); 355 } 356 357 Expected<orc::VModuleKey> addObject(std::unique_ptr<MemoryBuffer> ObjBuffer, 358 LLVMOrcSymbolResolverFn ExternalResolver, 359 void *ExternalResolverCtx) { 360 if (auto Obj = object::ObjectFile::createObjectFile( 361 ObjBuffer->getMemBufferRef())) { 362 363 auto K = ES.allocateVModule(); 364 Resolvers[K] = std::make_shared<CBindingsResolver>( 365 *this, ExternalResolver, ExternalResolverCtx); 366 367 if (auto Err = ObjectLayer.addObject(K, std::move(ObjBuffer))) 368 return std::move(Err); 369 370 KeyLayers[K] = detail::createGenericLayer(ObjectLayer); 371 372 return K; 373 } else 374 return Obj.takeError(); 375 } 376 377 JITSymbol findSymbol(const std::string &Name, 378 bool ExportedSymbolsOnly) { 379 if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly)) 380 return Sym; 381 if (CODLayer) 382 return CODLayer->findSymbol(mangle(Name), ExportedSymbolsOnly); 383 return CompileLayer.findSymbol(mangle(Name), ExportedSymbolsOnly); 384 } 385 386 JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name, 387 bool ExportedSymbolsOnly) { 388 assert(KeyLayers.count(K) && "looking up symbol in unknown module"); 389 return KeyLayers[K]->findSymbolIn(K, mangle(Name), ExportedSymbolsOnly); 390 } 391 392 Expected<JITTargetAddress> findSymbolAddress(const std::string &Name, 393 bool ExportedSymbolsOnly) { 394 if (auto Sym = findSymbol(Name, ExportedSymbolsOnly)) { 395 // Successful lookup, non-null symbol: 396 if (auto AddrOrErr = Sym.getAddress()) 397 return *AddrOrErr; 398 else 399 return AddrOrErr.takeError(); 400 } else if (auto Err = Sym.takeError()) { 401 // Lookup failure - report error. 402 return std::move(Err); 403 } 404 405 // No symbol not found. Return 0. 406 return 0; 407 } 408 409 Expected<JITTargetAddress> findSymbolAddressIn(orc::VModuleKey K, 410 const std::string &Name, 411 bool ExportedSymbolsOnly) { 412 if (auto Sym = findSymbolIn(K, Name, ExportedSymbolsOnly)) { 413 // Successful lookup, non-null symbol: 414 if (auto AddrOrErr = Sym.getAddress()) 415 return *AddrOrErr; 416 else 417 return AddrOrErr.takeError(); 418 } else if (auto Err = Sym.takeError()) { 419 // Lookup failure - report error. 420 return std::move(Err); 421 } 422 423 // Symbol not found. Return 0. 424 return 0; 425 } 426 427 const std::string &getErrorMessage() const { return ErrMsg; } 428 429 void RegisterJITEventListener(JITEventListener *L) { 430 if (!L) 431 return; 432 EventListeners.push_back(L); 433 } 434 435 void UnregisterJITEventListener(JITEventListener *L) { 436 if (!L) 437 return; 438 439 auto I = find(reverse(EventListeners), L); 440 if (I != EventListeners.rend()) { 441 std::swap(*I, EventListeners.back()); 442 EventListeners.pop_back(); 443 } 444 } 445 446private: 447 using ResolverMap = 448 std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>>; 449 450 static std::unique_ptr<CompileCallbackMgr> 451 createCompileCallbackManager(TargetMachine &TM, orc::ExecutionSession &ES) { 452 auto CCMgr = createLocalCompileCallbackManager(TM.getTargetTriple(), ES, 0); 453 if (!CCMgr) { 454 // FIXME: It would be good if we could report this somewhere, but we do 455 // have an instance yet. 456 logAllUnhandledErrors(CCMgr.takeError(), errs(), "ORC error: "); 457 return nullptr; 458 } 459 return std::move(*CCMgr); 460 } 461 462 static std::unique_ptr<CODLayerT> 463 createCODLayer(orc::ExecutionSession &ES, CompileLayerT &CompileLayer, 464 CompileCallbackMgr *CCMgr, 465 IndirectStubsManagerBuilder IndirectStubsMgrBuilder, 466 ResolverMap &Resolvers) { 467 // If there is no compile callback manager available we can not create a 468 // compile on demand layer. 469 if (!CCMgr) 470 return nullptr; 471 472 return std::make_unique<CODLayerT>( 473 AcknowledgeORCv1Deprecation, ES, CompileLayer, 474 [&Resolvers](orc::VModuleKey K) { 475 auto ResolverI = Resolvers.find(K); 476 assert(ResolverI != Resolvers.end() && "No resolver for module K"); 477 return ResolverI->second; 478 }, 479 [&Resolvers](orc::VModuleKey K, 480 std::shared_ptr<orc::SymbolResolver> Resolver) { 481 assert(!Resolvers.count(K) && "Resolver already present"); 482 Resolvers[K] = std::move(Resolver); 483 }, 484 [](Function &F) { return std::set<Function *>({&F}); }, *CCMgr, 485 std::move(IndirectStubsMgrBuilder), false); 486 } 487 488 void reportError(Error Err) { 489 // FIXME: Report errors on the execution session. 490 logAllUnhandledErrors(std::move(Err), errs(), "ORC error: "); 491 }; 492 493 void notifyFinalized(orc::VModuleKey K, 494 const object::ObjectFile &Obj, 495 const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) { 496 uint64_t Key = static_cast<uint64_t>( 497 reinterpret_cast<uintptr_t>(Obj.getData().data())); 498 for (auto &Listener : EventListeners) 499 Listener->notifyObjectLoaded(Key, Obj, LoadedObjInfo); 500 } 501 502 void notifyFreed(orc::VModuleKey K, const object::ObjectFile &Obj) { 503 uint64_t Key = static_cast<uint64_t>( 504 reinterpret_cast<uintptr_t>(Obj.getData().data())); 505 for (auto &Listener : EventListeners) 506 Listener->notifyFreeingObject(Key); 507 } 508 509 orc::ExecutionSession ES; 510 std::unique_ptr<CompileCallbackMgr> CCMgr; 511 512 std::vector<JITEventListener *> EventListeners; 513 514 DataLayout DL; 515 SectionMemoryManager CCMgrMemMgr; 516 517 std::unique_ptr<orc::IndirectStubsManager> IndirectStubsMgr; 518 519 ObjLayerT ObjectLayer; 520 CompileLayerT CompileLayer; 521 std::unique_ptr<CODLayerT> CODLayer; 522 523 std::map<orc::VModuleKey, std::unique_ptr<detail::GenericLayer>> KeyLayers; 524 525 orc::LegacyLocalCXXRuntimeOverrides CXXRuntimeOverrides; 526 std::vector<orc::LegacyCtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners; 527 std::string ErrMsg; 528 529 ResolverMap Resolvers; 530}; 531 532} // end namespace llvm 533 534#endif // LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H 535