1 //===--------------- OrcV2CBindings.cpp - C bindings OrcV2 APIs -----------===// 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 #include "llvm-c/LLJIT.h" 10 #include "llvm-c/Orc.h" 11 #include "llvm-c/OrcEE.h" 12 #include "llvm-c/TargetMachine.h" 13 14 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" 15 #include "llvm/ExecutionEngine/Orc/LLJIT.h" 16 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" 17 #include "llvm/ExecutionEngine/SectionMemoryManager.h" 18 19 using namespace llvm; 20 using namespace llvm::orc; 21 22 namespace llvm { 23 namespace orc { 24 25 class InProgressLookupState; 26 27 class OrcV2CAPIHelper { 28 public: 29 using PoolEntry = SymbolStringPtr::PoolEntry; 30 using PoolEntryPtr = SymbolStringPtr::PoolEntryPtr; 31 32 static PoolEntryPtr releaseSymbolStringPtr(SymbolStringPtr S) { 33 PoolEntryPtr Result = nullptr; 34 std::swap(Result, S.S); 35 return Result; 36 } 37 38 static SymbolStringPtr retainSymbolStringPtr(PoolEntryPtr P) { 39 return SymbolStringPtr(P); 40 } 41 42 static PoolEntryPtr getRawPoolEntryPtr(const SymbolStringPtr &S) { 43 return S.S; 44 } 45 46 static void retainPoolEntry(PoolEntryPtr P) { 47 SymbolStringPtr S(P); 48 S.S = nullptr; 49 } 50 51 static void releasePoolEntry(PoolEntryPtr P) { 52 SymbolStringPtr S; 53 S.S = P; 54 } 55 56 static InProgressLookupState *extractLookupState(LookupState &LS) { 57 return LS.IPLS.release(); 58 } 59 60 static void resetLookupState(LookupState &LS, InProgressLookupState *IPLS) { 61 return LS.reset(IPLS); 62 } 63 }; 64 65 } // namespace orc 66 } // namespace llvm 67 68 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionSession, LLVMOrcExecutionSessionRef) 69 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SymbolStringPool, LLVMOrcSymbolStringPoolRef) 70 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcV2CAPIHelper::PoolEntry, 71 LLVMOrcSymbolStringPoolEntryRef) 72 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MaterializationUnit, 73 LLVMOrcMaterializationUnitRef) 74 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITDylib, LLVMOrcJITDylibRef) 75 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ResourceTracker, LLVMOrcResourceTrackerRef) 76 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DefinitionGenerator, 77 LLVMOrcDefinitionGeneratorRef) 78 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(InProgressLookupState, LLVMOrcLookupStateRef) 79 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeContext, 80 LLVMOrcThreadSafeContextRef) 81 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeModule, LLVMOrcThreadSafeModuleRef) 82 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITTargetMachineBuilder, 83 LLVMOrcJITTargetMachineBuilderRef) 84 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ObjectLayer, LLVMOrcObjectLayerRef) 85 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJITBuilder, LLVMOrcLLJITBuilderRef) 86 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJIT, LLVMOrcLLJITRef) 87 88 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) 89 90 namespace llvm { 91 namespace orc { 92 93 class CAPIDefinitionGenerator final : public DefinitionGenerator { 94 public: 95 CAPIDefinitionGenerator( 96 void *Ctx, 97 LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction TryToGenerate) 98 : Ctx(Ctx), TryToGenerate(TryToGenerate) {} 99 100 Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, 101 JITDylibLookupFlags JDLookupFlags, 102 const SymbolLookupSet &LookupSet) override { 103 104 // Take the lookup state. 105 LLVMOrcLookupStateRef LSR = ::wrap(OrcV2CAPIHelper::extractLookupState(LS)); 106 107 // Translate the lookup kind. 108 LLVMOrcLookupKind CLookupKind; 109 switch (K) { 110 case LookupKind::Static: 111 CLookupKind = LLVMOrcLookupKindStatic; 112 break; 113 case LookupKind::DLSym: 114 CLookupKind = LLVMOrcLookupKindDLSym; 115 break; 116 } 117 118 // Translate the JITDylibSearchFlags. 119 LLVMOrcJITDylibLookupFlags CJDLookupFlags; 120 switch (JDLookupFlags) { 121 case JITDylibLookupFlags::MatchExportedSymbolsOnly: 122 CJDLookupFlags = LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly; 123 break; 124 case JITDylibLookupFlags::MatchAllSymbols: 125 CJDLookupFlags = LLVMOrcJITDylibLookupFlagsMatchAllSymbols; 126 break; 127 } 128 129 // Translate the lookup set. 130 std::vector<LLVMOrcCLookupSetElement> CLookupSet; 131 CLookupSet.reserve(LookupSet.size()); 132 for (auto &KV : LookupSet) { 133 LLVMOrcSymbolLookupFlags SLF; 134 LLVMOrcSymbolStringPoolEntryRef Name = 135 ::wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(KV.first)); 136 switch (KV.second) { 137 case SymbolLookupFlags::RequiredSymbol: 138 SLF = LLVMOrcSymbolLookupFlagsRequiredSymbol; 139 break; 140 case SymbolLookupFlags::WeaklyReferencedSymbol: 141 SLF = LLVMOrcSymbolLookupFlagsWeaklyReferencedSymbol; 142 break; 143 } 144 CLookupSet.push_back({Name, SLF}); 145 } 146 147 // Run the C TryToGenerate function. 148 auto Err = unwrap(TryToGenerate(::wrap(this), Ctx, &LSR, CLookupKind, 149 ::wrap(&JD), CJDLookupFlags, 150 CLookupSet.data(), CLookupSet.size())); 151 152 // Restore the lookup state. 153 OrcV2CAPIHelper::resetLookupState(LS, ::unwrap(LSR)); 154 155 return Err; 156 } 157 158 private: 159 void *Ctx; 160 LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction TryToGenerate; 161 }; 162 163 } // end namespace orc 164 } // end namespace llvm 165 166 void LLVMOrcExecutionSessionSetErrorReporter( 167 LLVMOrcExecutionSessionRef ES, LLVMOrcErrorReporterFunction ReportError, 168 void *Ctx) { 169 unwrap(ES)->setErrorReporter( 170 [=](Error Err) { ReportError(Ctx, wrap(std::move(Err))); }); 171 } 172 173 LLVMOrcSymbolStringPoolRef 174 LLVMOrcExecutionSessionGetSymbolStringPool(LLVMOrcExecutionSessionRef ES) { 175 return wrap(unwrap(ES)->getSymbolStringPool().get()); 176 } 177 178 void LLVMOrcSymbolStringPoolClearDeadEntries(LLVMOrcSymbolStringPoolRef SSP) { 179 unwrap(SSP)->clearDeadEntries(); 180 } 181 182 LLVMOrcSymbolStringPoolEntryRef 183 LLVMOrcExecutionSessionIntern(LLVMOrcExecutionSessionRef ES, const char *Name) { 184 return wrap( 185 OrcV2CAPIHelper::releaseSymbolStringPtr(unwrap(ES)->intern(Name))); 186 } 187 188 void LLVMOrcRetainSymbolStringPoolEntry(LLVMOrcSymbolStringPoolEntryRef S) { 189 OrcV2CAPIHelper::retainPoolEntry(unwrap(S)); 190 } 191 192 void LLVMOrcReleaseSymbolStringPoolEntry(LLVMOrcSymbolStringPoolEntryRef S) { 193 OrcV2CAPIHelper::releasePoolEntry(unwrap(S)); 194 } 195 196 const char *LLVMOrcSymbolStringPoolEntryStr(LLVMOrcSymbolStringPoolEntryRef S) { 197 return unwrap(S)->getKey().data(); 198 } 199 200 LLVMOrcResourceTrackerRef 201 LLVMOrcJITDylibCreateResourceTracker(LLVMOrcJITDylibRef JD) { 202 auto RT = unwrap(JD)->createResourceTracker(); 203 // Retain the pointer for the C API client. 204 RT->Retain(); 205 return wrap(RT.get()); 206 } 207 208 LLVMOrcResourceTrackerRef 209 LLVMOrcJITDylibGetDefaultResourceTracker(LLVMOrcJITDylibRef JD) { 210 auto RT = unwrap(JD)->getDefaultResourceTracker(); 211 // Retain the pointer for the C API client. 212 return wrap(RT.get()); 213 } 214 215 void LLVMOrcReleaseResourceTracker(LLVMOrcResourceTrackerRef RT) { 216 ResourceTrackerSP TmpRT(unwrap(RT)); 217 TmpRT->Release(); 218 } 219 220 void LLVMOrcResourceTrackerTransferTo(LLVMOrcResourceTrackerRef SrcRT, 221 LLVMOrcResourceTrackerRef DstRT) { 222 ResourceTrackerSP TmpRT(unwrap(SrcRT)); 223 TmpRT->transferTo(*unwrap(DstRT)); 224 } 225 226 LLVMErrorRef LLVMOrcResourceTrackerRemove(LLVMOrcResourceTrackerRef RT) { 227 ResourceTrackerSP TmpRT(unwrap(RT)); 228 return wrap(TmpRT->remove()); 229 } 230 231 void LLVMOrcDisposeDefinitionGenerator(LLVMOrcDefinitionGeneratorRef DG) { 232 std::unique_ptr<DefinitionGenerator> TmpDG(unwrap(DG)); 233 } 234 235 void LLVMOrcDisposeMaterializationUnit(LLVMOrcMaterializationUnitRef MU) { 236 std::unique_ptr<MaterializationUnit> TmpMU(unwrap(MU)); 237 } 238 239 LLVMOrcMaterializationUnitRef 240 LLVMOrcAbsoluteSymbols(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs) { 241 SymbolMap SM; 242 for (size_t I = 0; I != NumPairs; ++I) { 243 JITSymbolFlags Flags; 244 245 if (Syms[I].Sym.Flags.GenericFlags & LLVMJITSymbolGenericFlagsExported) 246 Flags |= JITSymbolFlags::Exported; 247 if (Syms[I].Sym.Flags.GenericFlags & LLVMJITSymbolGenericFlagsWeak) 248 Flags |= JITSymbolFlags::Weak; 249 250 Flags.getTargetFlags() = Syms[I].Sym.Flags.TargetFlags; 251 252 SM[OrcV2CAPIHelper::retainSymbolStringPtr(unwrap(Syms[I].Name))] = 253 JITEvaluatedSymbol(Syms[I].Sym.Address, Flags); 254 } 255 256 return wrap(absoluteSymbols(std::move(SM)).release()); 257 } 258 259 LLVMOrcJITDylibRef 260 LLVMOrcExecutionSessionCreateBareJITDylib(LLVMOrcExecutionSessionRef ES, 261 const char *Name) { 262 return wrap(&unwrap(ES)->createBareJITDylib(Name)); 263 } 264 265 LLVMErrorRef 266 LLVMOrcExecutionSessionCreateJITDylib(LLVMOrcExecutionSessionRef ES, 267 LLVMOrcJITDylibRef *Result, 268 const char *Name) { 269 auto JD = unwrap(ES)->createJITDylib(Name); 270 if (!JD) 271 return wrap(JD.takeError()); 272 *Result = wrap(&*JD); 273 return LLVMErrorSuccess; 274 } 275 276 LLVMOrcJITDylibRef 277 LLVMOrcExecutionSessionGetJITDylibByName(LLVMOrcExecutionSessionRef ES, 278 const char *Name) { 279 return wrap(unwrap(ES)->getJITDylibByName(Name)); 280 } 281 282 LLVMErrorRef LLVMOrcJITDylibDefine(LLVMOrcJITDylibRef JD, 283 LLVMOrcMaterializationUnitRef MU) { 284 std::unique_ptr<MaterializationUnit> TmpMU(unwrap(MU)); 285 286 if (auto Err = unwrap(JD)->define(TmpMU)) { 287 TmpMU.release(); 288 return wrap(std::move(Err)); 289 } 290 return LLVMErrorSuccess; 291 } 292 293 LLVMErrorRef LLVMOrcJITDylibClear(LLVMOrcJITDylibRef JD) { 294 return wrap(unwrap(JD)->clear()); 295 } 296 297 void LLVMOrcJITDylibAddGenerator(LLVMOrcJITDylibRef JD, 298 LLVMOrcDefinitionGeneratorRef DG) { 299 unwrap(JD)->addGenerator(std::unique_ptr<DefinitionGenerator>(unwrap(DG))); 300 } 301 302 LLVMOrcDefinitionGeneratorRef LLVMOrcCreateCustomCAPIDefinitionGenerator( 303 LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction F, void *Ctx) { 304 auto DG = std::make_unique<CAPIDefinitionGenerator>(Ctx, F); 305 return wrap(DG.release()); 306 } 307 308 LLVMErrorRef LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess( 309 LLVMOrcDefinitionGeneratorRef *Result, char GlobalPrefix, 310 LLVMOrcSymbolPredicate Filter, void *FilterCtx) { 311 assert(Result && "Result can not be null"); 312 assert((Filter || !FilterCtx) && 313 "if Filter is null then FilterCtx must also be null"); 314 315 DynamicLibrarySearchGenerator::SymbolPredicate Pred; 316 if (Filter) 317 Pred = [=](const SymbolStringPtr &Name) -> bool { 318 return Filter(FilterCtx, wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(Name))); 319 }; 320 321 auto ProcessSymsGenerator = 322 DynamicLibrarySearchGenerator::GetForCurrentProcess(GlobalPrefix, Pred); 323 324 if (!ProcessSymsGenerator) { 325 *Result = 0; 326 return wrap(ProcessSymsGenerator.takeError()); 327 } 328 329 *Result = wrap(ProcessSymsGenerator->release()); 330 return LLVMErrorSuccess; 331 } 332 333 LLVMOrcThreadSafeContextRef LLVMOrcCreateNewThreadSafeContext(void) { 334 return wrap(new ThreadSafeContext(std::make_unique<LLVMContext>())); 335 } 336 337 LLVMContextRef 338 LLVMOrcThreadSafeContextGetContext(LLVMOrcThreadSafeContextRef TSCtx) { 339 return wrap(unwrap(TSCtx)->getContext()); 340 } 341 342 void LLVMOrcDisposeThreadSafeContext(LLVMOrcThreadSafeContextRef TSCtx) { 343 delete unwrap(TSCtx); 344 } 345 346 LLVMOrcThreadSafeModuleRef 347 LLVMOrcCreateNewThreadSafeModule(LLVMModuleRef M, 348 LLVMOrcThreadSafeContextRef TSCtx) { 349 return wrap( 350 new ThreadSafeModule(std::unique_ptr<Module>(unwrap(M)), *unwrap(TSCtx))); 351 } 352 353 void LLVMOrcDisposeThreadSafeModule(LLVMOrcThreadSafeModuleRef TSM) { 354 delete unwrap(TSM); 355 } 356 357 LLVMErrorRef LLVMOrcJITTargetMachineBuilderDetectHost( 358 LLVMOrcJITTargetMachineBuilderRef *Result) { 359 assert(Result && "Result can not be null"); 360 361 auto JTMB = JITTargetMachineBuilder::detectHost(); 362 if (!JTMB) { 363 Result = 0; 364 return wrap(JTMB.takeError()); 365 } 366 367 *Result = wrap(new JITTargetMachineBuilder(std::move(*JTMB))); 368 return LLVMErrorSuccess; 369 } 370 371 LLVMOrcJITTargetMachineBuilderRef 372 LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM) { 373 auto *TemplateTM = unwrap(TM); 374 375 auto JTMB = 376 std::make_unique<JITTargetMachineBuilder>(TemplateTM->getTargetTriple()); 377 378 (*JTMB) 379 .setCPU(TemplateTM->getTargetCPU().str()) 380 .setRelocationModel(TemplateTM->getRelocationModel()) 381 .setCodeModel(TemplateTM->getCodeModel()) 382 .setCodeGenOptLevel(TemplateTM->getOptLevel()) 383 .setFeatures(TemplateTM->getTargetFeatureString()) 384 .setOptions(TemplateTM->Options); 385 386 LLVMDisposeTargetMachine(TM); 387 388 return wrap(JTMB.release()); 389 } 390 391 void LLVMOrcDisposeJITTargetMachineBuilder( 392 LLVMOrcJITTargetMachineBuilderRef JTMB) { 393 delete unwrap(JTMB); 394 } 395 396 void LLVMOrcDisposeObjectLayer(LLVMOrcObjectLayerRef ObjLayer) { 397 delete unwrap(ObjLayer); 398 } 399 400 LLVMOrcLLJITBuilderRef LLVMOrcCreateLLJITBuilder(void) { 401 return wrap(new LLJITBuilder()); 402 } 403 404 void LLVMOrcDisposeLLJITBuilder(LLVMOrcLLJITBuilderRef Builder) { 405 delete unwrap(Builder); 406 } 407 408 void LLVMOrcLLJITBuilderSetJITTargetMachineBuilder( 409 LLVMOrcLLJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMB) { 410 unwrap(Builder)->setJITTargetMachineBuilder(*unwrap(JTMB)); 411 } 412 413 void LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator( 414 LLVMOrcLLJITBuilderRef Builder, 415 LLVMOrcLLJITBuilderObjectLinkingLayerCreatorFunction F, void *Ctx) { 416 unwrap(Builder)->setObjectLinkingLayerCreator( 417 [=](ExecutionSession &ES, const Triple &TT) { 418 auto TTStr = TT.str(); 419 return std::unique_ptr<ObjectLayer>( 420 unwrap(F(Ctx, wrap(&ES), TTStr.c_str()))); 421 }); 422 } 423 424 LLVMErrorRef LLVMOrcCreateLLJIT(LLVMOrcLLJITRef *Result, 425 LLVMOrcLLJITBuilderRef Builder) { 426 assert(Result && "Result can not be null"); 427 428 if (!Builder) 429 Builder = LLVMOrcCreateLLJITBuilder(); 430 431 auto J = unwrap(Builder)->create(); 432 LLVMOrcDisposeLLJITBuilder(Builder); 433 434 if (!J) { 435 Result = 0; 436 return wrap(J.takeError()); 437 } 438 439 *Result = wrap(J->release()); 440 return LLVMErrorSuccess; 441 } 442 443 LLVMErrorRef LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J) { 444 delete unwrap(J); 445 return LLVMErrorSuccess; 446 } 447 448 LLVMOrcExecutionSessionRef LLVMOrcLLJITGetExecutionSession(LLVMOrcLLJITRef J) { 449 return wrap(&unwrap(J)->getExecutionSession()); 450 } 451 452 LLVMOrcJITDylibRef LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J) { 453 return wrap(&unwrap(J)->getMainJITDylib()); 454 } 455 456 const char *LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J) { 457 return unwrap(J)->getTargetTriple().str().c_str(); 458 } 459 460 char LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J) { 461 return unwrap(J)->getDataLayout().getGlobalPrefix(); 462 } 463 464 LLVMOrcSymbolStringPoolEntryRef 465 LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName) { 466 return wrap(OrcV2CAPIHelper::releaseSymbolStringPtr( 467 unwrap(J)->mangleAndIntern(UnmangledName))); 468 } 469 470 LLVMErrorRef LLVMOrcLLJITAddObjectFile(LLVMOrcLLJITRef J, LLVMOrcJITDylibRef JD, 471 LLVMMemoryBufferRef ObjBuffer) { 472 return wrap(unwrap(J)->addObjectFile( 473 *unwrap(JD), std::unique_ptr<MemoryBuffer>(unwrap(ObjBuffer)))); 474 } 475 476 LLVMErrorRef LLVMOrcLLJITAddObjectFileWithRT(LLVMOrcLLJITRef J, 477 LLVMOrcResourceTrackerRef RT, 478 LLVMMemoryBufferRef ObjBuffer) { 479 return wrap(unwrap(J)->addObjectFile( 480 ResourceTrackerSP(unwrap(RT)), 481 std::unique_ptr<MemoryBuffer>(unwrap(ObjBuffer)))); 482 } 483 484 LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J, 485 LLVMOrcJITDylibRef JD, 486 LLVMOrcThreadSafeModuleRef TSM) { 487 std::unique_ptr<ThreadSafeModule> TmpTSM(unwrap(TSM)); 488 return wrap(unwrap(J)->addIRModule(*unwrap(JD), std::move(*TmpTSM))); 489 } 490 491 LLVMErrorRef LLVMOrcLLJITAddLLVMIRModuleWithRT(LLVMOrcLLJITRef J, 492 LLVMOrcResourceTrackerRef RT, 493 LLVMOrcThreadSafeModuleRef TSM) { 494 std::unique_ptr<ThreadSafeModule> TmpTSM(unwrap(TSM)); 495 return wrap(unwrap(J)->addIRModule(ResourceTrackerSP(unwrap(RT)), 496 std::move(*TmpTSM))); 497 } 498 499 LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J, 500 LLVMOrcJITTargetAddress *Result, 501 const char *Name) { 502 assert(Result && "Result can not be null"); 503 504 auto Sym = unwrap(J)->lookup(Name); 505 if (!Sym) { 506 *Result = 0; 507 return wrap(Sym.takeError()); 508 } 509 510 *Result = Sym->getAddress(); 511 return LLVMErrorSuccess; 512 } 513 514 LLVMOrcObjectLayerRef 515 LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager( 516 LLVMOrcExecutionSessionRef ES) { 517 assert(ES && "ES must not be null"); 518 return wrap(new RTDyldObjectLinkingLayer( 519 *unwrap(ES), [] { return std::make_unique<SectionMemoryManager>(); })); 520 } 521 522 void LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener( 523 LLVMOrcObjectLayerRef RTDyldObjLinkingLayer, 524 LLVMJITEventListenerRef Listener) { 525 assert(RTDyldObjLinkingLayer && "RTDyldObjLinkingLayer must not be null"); 526 assert(Listener && "Listener must not be null"); 527 reinterpret_cast<RTDyldObjectLinkingLayer *>(unwrap(RTDyldObjLinkingLayer)) 528 ->registerJITEventListener(*unwrap(Listener)); 529 } 530